From 4c4b01f26584ca7ecd7ccdbf67ef031de88608a9 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Mon, 15 Jun 2026 11:07:23 -0500 Subject: [PATCH] Add a feature roadmap and implementation plan for a new daily report --- docs/roadmap/daily.md | 434 +++++++++++++ docs/roadmap/implementation.md | 1089 +++++++++++++++++--------------- 2 files changed, 1023 insertions(+), 500 deletions(-) create mode 100644 docs/roadmap/daily.md diff --git a/docs/roadmap/daily.md b/docs/roadmap/daily.md new file mode 100644 index 0000000..e2b2ec4 --- /dev/null +++ b/docs/roadmap/daily.md @@ -0,0 +1,434 @@ +# 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. diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index bfe8445..087485e 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,601 +1,690 @@ -# Today Report Implementation Roadmap +# Daily Report Implementation Roadmap ## Purpose This roadmap defines the staged implementation plan for -`docs/roadmap/today.md`. It is written for an LLM coding agent that will -implement each stage in order. +`docs/roadmap/daily.md`. It is written for an LLM coding agent that will +implement the new generated-text-template `daily` report in order. -This is a planning document only. It may describe unimplemented behavior because -it lives under `docs/roadmap/`. +The target feature is a clean replacement of the existing active Daily path: +`weatherreporter generate daily` should run a new independent `daily` report +that requires `--date YYYY-MM-DD`, uses generated structured text plus a +Markdown template, and initially renders the same report shape as `tomorrow`. + +This file is planning-only. Non-roadmap documentation should be updated only in +the implementation stage after the behavior exists. ## Source Roadmap -`docs/roadmap/today.md` is the feature roadmap and target-state authority for -the Today report. This implementation plan provides the concrete sequence for -reaching that target. - -If this implementation plan and `today.md` conflict, update the feature roadmap -first so it remains the conceptual source of truth, then update this file. +Use `docs/roadmap/daily.md` as the feature roadmap and source of user intent. +That document defines the target state, report identity, command behavior, +module composition, generated-text contract, and replacement policy for the +legacy `daily_today` report. ## Locked Decisions -- `today` is a new independent generated-text-template report. -- `today` does not replace the existing `daily_today` report in this roadmap. -- `weatherreporter generate today` is a new public command. -- `weatherreporter generate daily` remains the existing daily command and must - not alias to Today. -- `reports.today` is a new independent config override key. -- `reports.daily` and `reports.daily_today` remain mapped to the existing daily - report while that report exists. -- Morning batch includes `today` in the position currently occupied by - `daily_today`. -- Morning batch should not include both `today` and `daily_today`. -- Evening batch remains `tomorrow`. -- New Today runtime identity uses report ID `today`, artifact group `today`, - batch output `today.md`, template ID `today`, generated-text schema ID - `today`, and prompt ID `weather.today_generated_text`. -- Historical `daily_today` workspace artifacts are not migrated. -- Today uses its own deterministic `today_planning` module. -- Today does not reuse Tomorrow's prompt, template, schema, report ID, artifact - group, or public planning stanza. -- Scriptorium registration remains out of band. Weatherreporter invokes - Scriptorium by prompt ID and passes the data package as it does for existing - generated-text reports. +- `daily` is a separate report ID, not an alias for `today`, `tomorrow`, or + legacy `daily_today`. +- `weatherreporter generate daily` remains the public command, but it must run + the new generated-text-template Daily report. +- `weatherreporter generate daily` requires `--date YYYY-MM-DD`. +- The supplied date is interpreted as a local civil date in the effective + report timezone after config and `--tz` overrides. +- The valid period is `[00:00, next 00:00)` for the selected local civil day. +- Daily is manually targeted and is not added to morning or evening batches. +- Daily uses prompt ID `weather.daily_generated_text`. +- Daily uses template ID `daily` and generated-text schema ID `daily`. +- Daily uses artifact group `daily` and batch output name `daily.md`. +- Daily has its own generated-text type, schema, prompt asset, Markdown + template, render-context type, and planning module. +- Daily may share private helpers with Tomorrow when mechanics are identical, + but it must not expose Tomorrow-specific public types or stanzas. +- Remove active `daily_today` report definition and `reports.daily_today` + config-key support. +- Historical workspace artifacts with `daily_today` metadata are not migrated. ## Implementation Principles -- Keep report identity and public name resolution in `internal/report`. -- Keep CLI parsing in `internal/cli`; do not move domain policy into CLI. -- Keep generated-text validation and render-context construction in - `internal/generatedtext`. -- Keep embedded schema/template assets in `internal/reporttemplate`. -- Keep module IDs in `internal/module` and module builders in - `internal/briefing`. -- Keep the app orchestration path shared with other generated-text-template - reports. -- Do not introduce a new workflow engine, CLI framework, plugin system, or - compatibility migration layer for old workspace artifacts. -- Do not make `daily` and `today` compatibility aliases. -- Preserve existing managed artifact layout conventions. +- Preserve public CLI syntax except for the intentional breaking change that + `generate daily` now requires `--date`. +- Keep report identity, prompt IDs, generation mode, module order, artifact + groups, batch membership, and compatibility policy centralized in + `internal/report`. +- Keep CLI parsing in `internal/cli`; enforce the missing-date policy in both + CLI parsing and the report resolver so non-CLI callers cannot accidentally + generate an undated Daily report. +- Keep generated-text schema validation in `internal/generatedtext`. +- Keep embedded schemas, prompts, and templates as separate files under + `internal/reporttemplate`. +- Keep deterministic module output in `internal/briefing` and module IDs/options + in `internal/module`. +- Do not add compatibility aliases for `daily_today`. +- Update implemented documentation only after the code behavior exists. -## Stage 1: Today ID Scaffold And Planning Module +## Stage 1: Daily Planning Module -Goal: add the internal Today report ID scaffold and Today planning module -without making Today public or changing batch behavior yet. +### Goal -This stage should compile and pass focused module/report tests while the -existing active `daily_today` report remains unchanged. - -### Implementation - -- In `internal/report/definition.go`, add `Today ID = "today"`. -- Do not remove or alter `DailyToday` in this stage. -- In `internal/module/module.go`, add: - - `TodayPlanning ID = "today_planning"`; - - `TodayPlanningOptions struct{}`. -- Add `internal/briefing/today_planning_module.go`. -- Add `TodayPlanningModule` with initial prompt-facing fields: - - `morning_readiness`; - - `commute_school_workday_concerns`; - - `outdoor_planning`; - - `late_day_change_watch`. -- Add a private deterministic helper, such as `buildTodayPlanning`, near the - existing planning summary helpers. -- Reuse private helper functions from Tomorrow planning only when the - underlying logic is identical. Do not expose or reuse `TomorrowPlanningModule` - or the `tomorrow_planning` stanza. -- Register `TodayPlanning` in `internal/briefing/modules.go` with: - - stanza name `today_planning`; - - supported reports `[]report.ID{report.Today}`; - - required derived facts matching the daily-summary/daypart facts it uses; - - `MissingDataEmpty` unless implementation discovers a stricter requirement - is needed. -- Add `report.Today` to module support lists where Today should be eligible: - - all-report modules; - - daypart modules; - - narrative forecast; - - hourly forecast; - - derived daily summary; - - derived daypart summaries. -- Keep existing `report.DailyToday` support unchanged. +Add the Daily-specific planning module before activating the new report. This +keeps module and report work separable and makes the eventual Daily default +composition explicit. ### Files To Inspect -- `internal/report/definition.go` - `internal/module/module.go` -- `internal/briefing/modules.go` - `internal/briefing/tomorrow_planning_module.go` -- `internal/briefing/summary_helpers.go` +- `internal/briefing/today_planning_module.go` +- `internal/briefing/modules.go` - `internal/briefing/derived_modules_test.go` -- `internal/briefing/modules_test.go` - -### Acceptance Criteria - -- `module.TodayPlanning` is registered and buildable for `report.Today`. -- `today_planning` is rejected for unsupported reports. -- The new module emits deterministic snake_case JSON fields. -- Existing Tomorrow planning behavior is unchanged. -- Existing Daily Today behavior is unchanged. - -### Tests - -Add or update tests for: - -- Today planning output shape. -- Today planning supported report validation. -- Unsupported report validation, including Tomorrow and Daily Today. -- Empty/fallback behavior when useful planning facts are missing. - -Run: - -```sh -go test ./internal/briefing ./internal/module ./internal/report -go test ./... -git diff --check -``` - -Stage size: suitable for one implementation prompt. - -## Stage 2: Today GeneratedText, Schema, Prompt, Template, And Render Context - -Goal: add Today generated-text assets and render-context support while keeping -the report inactive until Stage 3. +- `docs/roadmap/daily.md` ### Implementation -- Add `internal/generatedtext/today.go`. -- Add `generatedtext.Today` with fields: - - `Summary string`; - - `ForecastDiscussion []string`; - - `PrecipitationTiming string`; - - `Confidence string`. -- Add `ValidateToday` with Tomorrow-equivalent semantics: - - strict JSON; - - reject unknown fields; - - reject trailing JSON values; - - trim string fields; - - trim and drop blank discussion paragraphs; - - require nonblank `summary`; - - require at least one nonblank `forecast_discussion` paragraph; - - return canonical normalized JSON using the same public field names. -- Add `internal/reporttemplate/schemas/today.generated_text.schema.json`. -- Add `internal/reporttemplate/templates/today.md.tmpl`. -- Add `internal/reporttemplate/prompts/today.generated_text.md`. -- Add `TodayRenderContext`, `TodayReportContext`, `TodayTemplateModules`, and - `BuildTodayRenderContext` in `internal/generatedtext`. -- Today report context should include: - - `Title` exactly `Today's Weather`; - - `ForecastDate`; - - `ForecastDateLabel`; - - `ForecastDayName`; - - `GeneratedAt`; - - `GeneratedAtLabel`; - - `ValidPeriod`; - - `Timezone`. -- Today template modules should include at least: - - `Metadata`; - - `CurrentConditions`; - - `HourlyForecast`; - - `DerivedDailySummary`; - - `DerivedDaypartSummaries`; - - ordered daypart rows; - - `PrecipTiming`; - - `AlertDigest`; - - `SPCConvectiveOutlooks`; - - `AreaForecastDiscussion`; - - `SPCConvectiveDiscussion`; - - `WeatherStory`; - - `TodayPlanning`. -- Share private render-context helper mechanics with Tomorrow where appropriate, - such as snapshot lookup and daypart row ordering. -- Do not expose Tomorrow-specific types through the Today context. -- Register Today in the generated-text catalog with schema ID `today` and - template ID `today`. -- Add Today schema/template entries to `internal/reporttemplate` if explicit - asset maps are still used. -- The Today prompt asset should instruct the LLM to produce only the structured - JSON fields expected by the Today schema, using the data package as the only - weather source. +- Add `module.DailyPlanning` with value `daily_planning`. +- Add `module.DailyPlanningOptions struct{}`. +- Add `internal/briefing/daily_planning_module.go`. +- Add `DailyPlanningModule` with the initial fields: + - `morning_readiness` + - `commute_school_workday_concerns` + - `overnight_change_watch` +- Build the Daily planning module from the same underlying summary inputs as + Tomorrow planning, but do not reuse the public `TomorrowPlanningModule` type. +- Share private helper functions with Tomorrow only when the helper expresses + report-neutral mechanics. +- Register `daily_planning` in the default module registry with: + - stanza name `daily_planning` + - default options `module.DailyPlanningOptions{}` + - supported reports `[]report.ID{report.Daily}` after `report.Daily` exists + in Stage 3; if Stage 1 is implemented before `report.Daily`, add the module + ID/options now and wire report support in Stage 3. + +### Acceptance Criteria + +- `daily_planning` is a distinct module ID and stanza. +- No Daily path emits `tomorrow_planning`. +- No public Daily type aliases or embeds `TomorrowPlanningModule`. +- Unsupported reports receive an actionable unsupported-module error. + +### Tests + +- Add or update module tests for: + - output shape; + - missing-summary fallback behavior; + - supported Daily report; + - unsupported Today, Tomorrow, Hourly, Three-Day, Weekend, and Storm reports. +- Suggested focused command after this stage: + +```sh +go test ./internal/module ./internal/briefing +``` + +### Prompt Size + +Small enough for one implementation prompt. + +## Stage 2: Daily GeneratedText Contract And Assets + +### Goal + +Add Daily generated-text validation and embedded assets while keeping the active +report registry unchanged until Stage 3. ### Files To Inspect - `internal/generatedtext/tomorrow.go` -- `internal/generatedtext/render_context.go` +- `internal/generatedtext/today.go` - `internal/generatedtext/catalog.go` - `internal/generatedtext/*_test.go` - `internal/reporttemplate/reporttemplate.go` - `internal/reporttemplate/templates/tomorrow.md.tmpl` -- `internal/reporttemplate/schemas/tomorrow.generated_text.schema.json` - `internal/reporttemplate/prompts/tomorrow.generated_text.md` - -### Acceptance Criteria - -- Today generated-text validation mirrors Tomorrow behavior. -- Today schema accepts exactly the intended public fields. -- Today template renders from structured module data and generated text. -- Today render context uses Today-specific public types. -- Today generated-text catalog lookup works once a report definition references - schema/template ID `today`. -- Existing Hourly and Tomorrow generated-text behavior is unchanged. - -### Tests - -Add or update tests for: - -- `ValidateToday` success, missing required fields, unknown fields, trailing - JSON, malformed JSON, blank strings, paragraph trimming, and canonical JSON. -- Today JSON schema lookup. -- Today template lookup. -- Today render context labels, daypart ordering, populated modules, and nil - optional modules. -- Generated-text catalog completeness support for Today once the report - definition is active. If the report is not active until Stage 3, add this - assertion in Stage 3. - -Run: - -```sh -go test ./internal/generatedtext ./internal/reporttemplate ./internal/briefing -go test ./... -git diff --check -``` - -Stage size: suitable for one implementation prompt. - -## Stage 3: Today Report Definition And Batch Integration - -Goal: add Today as an active report and switch morning batch to Today without -aliasing or replacing the existing `daily` command/report. +- `internal/reporttemplate/schemas/tomorrow.generated_text.schema.json` +- `internal/reporttemplate/reporttemplate_test.go` ### Implementation -- Add a Today definition, preferably in a new `internal/report/today_report.go` - file. -- The Today definition must use: - - `ID: report.Today`; - - `Name: "Today Report"` or equivalent user-facing report name; - - `PromptID: "weather.today_generated_text"`; - - `GenerationMode: report.GenerationModeGeneratedTextTemplate`; - - `TemplateID: "today"`; - - `GeneratedTextSchemaID: "today"`; - - `ComparisonStrategy: report.CompareSameValidDate`; - - `ArtifactGroup: "today"`; - - `BatchOutputName: "today.md"`; - - `Generated: true`; - - `CompatiblePriorIDs: []report.ID{report.Today}`; - - `Morning: true`; - - current-local-civil-day resolver. -- Keep the existing Daily Today definition and report ID unchanged. -- Today default modules must include, in this order unless implementation tests - justify a more useful order: - - `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`; - - `hourly_forecast`; - - `today_planning`. -- Update `internal/report/registry.go`: - - default registry includes both Daily Today and Today; - - `All()` includes both reports in a stable order, with Today near the other - current-day report. -- Update `internal/report/period.go`: - - morning batch resolves Today first; - - morning batch does not include Daily Today; - - morning Sunday skip behavior for Weekend is unchanged; - - evening batch remains Tomorrow. -- Update report name helpers in `internal/report/names.go`: - - add `CommandNameToday = "today"`; - - `IDForCommandName("today") == report.Today`; - - `IDForCommandName("daily")` remains the existing Daily Today report; - - `CommandNames()` includes both `today` and `daily` as distinct commands. -- Update config-key resolution: - - `IDForConfigKey("today") == report.Today`; - - `IDForConfigKey("daily")` remains the existing Daily Today report; - - `IDForConfigKey("daily_today")` remains the existing Daily Today report. -- Update structured Recent Changes dispatch so Today uses the daily comparison - logic currently used by Daily Today and Tomorrow. -- Update briefing/package variant logic so Today produces variant `today`. +- Add `internal/generatedtext/daily.go`. +- Add `type Daily struct` with the same public JSON shape as Tomorrow: + - `summary` required string + - `forecast_discussion` required `[]string` + - `precipitation_timing` optional string + - `confidence` optional string +- Add `ValidateDaily`. +- Match Tomorrow validation semantics: + - reject malformed JSON; + - reject unknown fields; + - reject trailing values; + - trim string fields; + - trim each forecast-discussion paragraph; + - drop blank forecast-discussion paragraphs; + - require nonblank summary; + - require at least one nonblank forecast-discussion paragraph; + - return canonical normalized JSON. +- Add `internal/reporttemplate/schemas/daily.generated_text.schema.json`. +- Add `internal/reporttemplate/prompts/daily.generated_text.md`. +- Add `internal/reporttemplate/templates/daily.md.tmpl`, initially matching the + Tomorrow rendered Markdown structure while referencing Daily render-context + fields. +- Register Daily in the generated-text catalog with schema ID `daily`. +- Register the Daily schema and template asset lookup in `internal/reporttemplate`. + +### Acceptance Criteria + +- Daily generated text validates independently from Tomorrow. +- The Daily schema and template can be looked up by ID `daily`. +- The Daily prompt asset exists as maintained source material for out-of-band + Scriptorium registration. +- No report registry behavior changes yet unless Stage 2 and Stage 3 are + intentionally implemented together. + +### Tests + +- Add generated-text tests for: + - valid Daily JSON; + - missing `summary`; + - missing or blank `forecast_discussion`; + - unknown fields; + - trailing JSON; + - trimming and canonical output. +- Add catalog tests proving schema ID `daily` maps to `ValidateDaily`. +- Add reporttemplate tests for Daily schema lookup, template lookup, and basic + render behavior. +- Suggested focused command: + +```sh +go test ./internal/generatedtext ./internal/reporttemplate +``` + +### Prompt Size + +Small enough for one implementation prompt. + +## Stage 3: Daily Render Context + +### Goal + +Add a dedicated Daily template context that mirrors Tomorrow mechanics without +exposing Tomorrow public types. + +### Files To Inspect + +- `internal/generatedtext/render_context.go` +- `internal/generatedtext/render_context_test.go` +- `internal/briefing/*_module.go` +- `internal/module/module.go` +- `internal/facts` +- `internal/reporttemplate/templates/tomorrow.md.tmpl` + +### Implementation + +- Add: + +```go +type DailyRenderContext struct { + Report DailyReportContext + GeneratedText Daily + Modules DailyTemplateModules + Collected facts.CollectedFacts + Derived facts.DerivedFacts +} +``` + +- Add `DailyReportContext` with: + - `Title` + - `ForecastDate` + - `ForecastDateLabel` + - `ForecastDayName` + - `GeneratedAt` + - `GeneratedAtLabel` + - `ValidPeriod` + - `Timezone` +- Add `DailyTemplateModules` with the Daily template surfaces defined in + `docs/roadmap/daily.md`, including `DailyPlanning`. +- Add a Daily daypart context if the Tomorrow daypart context is not already + generic enough to use privately. +- Add `BuildDailyRenderContext`. +- Generate `Title` as `'s Weather`, for example `Monday's Weather`. +- Build `ForecastDateLabel` from the valid-period start in the effective + timezone. +- Reuse private module snapshot lookup and ordered-daypart helpers where useful, + but keep Daily's exported types distinct. + +### Acceptance Criteria + +- Daily render context is independent and template-friendly. +- Optional modules are nil when omitted by missing-data policy. +- Ordered dayparts use the same ordering and omission behavior as Tomorrow. +- Daily planning is available as `.Modules.DailyPlanning`. +- The render context exposes `Collected` and `Derived` for advanced template + use, consistent with current generated-text-template reports. + +### Tests + +- Add render-context tests for: + - title and forecast date label; + - generated-at label; + - valid period and timezone; + - Daily planning extraction; + - omitted optional modules; + - daypart ordering; + - collected and derived facts propagation. +- Suggested focused command: + +```sh +go test ./internal/generatedtext ./internal/reporttemplate +``` + +### Prompt Size + +Small enough for one implementation prompt. + +## Stage 4: Report Registry Cutover + +### Goal + +Replace the active legacy `daily_today` report definition with the new generated +text-template `daily` report. ### Files To Inspect - `internal/report/definition.go` - `internal/report/daily_report.go` -- `internal/report/registry.go` -- `internal/report/period.go` +- `internal/report/today_report.go` +- `internal/report/tomorrow_report.go` - `internal/report/names.go` +- `internal/report/period.go` - `internal/report/period_test.go` - `internal/briefing/modules.go` -- `internal/briefing/package.go` - `internal/app/app.go` -- `internal/config/reports.go` -- `internal/config/config_test.go` - `internal/changes` -### Acceptance Criteria - -- `report.DefaultRegistry()` has active definitions for both `today` and the - existing daily report. -- Morning batch report IDs are `today,three_day,weekend` when Weekend is - included. -- Sunday morning batch report IDs are `today,three_day`. -- `daily` and `today` command names resolve to different report IDs. -- `reports.today` and `reports.daily` / `reports.daily_today` resolve to - different report IDs. -- Today report metadata, RunID, artifact group, batch output name, data-package - path, report path, and distributor template values use `today`. -- Existing manual Daily, Tomorrow, Hourly, Three-Day, Weekend, and Storm - behavior is unchanged. - -### Tests - -Add or update tests for: - -- report registry membership and `All()` order; -- `IDForCommandName` for `today` and `daily`; -- `CommandNames()` stable order; -- `IDForConfigKey` for `today`, `daily`, and `daily_today`; -- proof that Today and Daily resolve to different report IDs; -- Today valid period with default current local date; -- Today valid period with explicit `--date` / request date; -- morning and Sunday morning batch order; -- Recent Changes dispatch for Today; -- module registry support for Today modules. - -Run: - -```sh -go test ./internal/report ./internal/config ./internal/briefing ./internal/changes -go test ./internal/app ./internal/cli -go test ./... -go run ./cmd/weatherreporter --help -git diff --check -``` - -Stage size: this is a broad but coherent report/batch integration stage. It is -suitable for one implementation prompt if the agent keeps the scope to report -identity and tests. - -## Stage 4: App, CLI, Config, And Workflow Integration - -Goal: make `generate today`, batches, artifacts, and distributor notification -work end-to-end through the existing app flow while keeping `generate daily` -separate. - ### Implementation -- Add `app.ReportToday` if app keeps report-kind constants. -- Keep `app.ReportDaily` mapped to the existing daily command/report. -- Update CLI help text to show `generate today` as a distinct command. -- Keep `generate daily` help text separate. -- Parse `--date YYYY-MM-DD` for Today. - - If omitted, use current local date in the configured timezone. - - Keep existing `daily --date` behavior unchanged. -- Ensure app generation resolves: - - `today` to `report.Today`; - - `daily` to the existing daily report. -- Ensure Today generated-text-template flow persists: - - raw generated text; - - structured Scriptorium run result; - - normalized generated text; - - render context; - - rendered Markdown report; - - metadata; - - optional output copy. -- Ensure Today prompt invocation uses `weather.today_generated_text`. -- Ensure Scriptorium output path for Today generated text is a JSON artifact, - matching existing generated-text-template reports. -- Ensure state and metadata inspection work for Today run IDs. -- Ensure distributor notification uses the managed Today Markdown report path, - not optional output copies. -- Ensure distributor template variables resolve with: - - `report_id=today`; - - `artifact_group=today`; - - `batch_output_name=today.md`; - - valid-period variables based on the Today valid period. -- Update fake Scriptorium scripts in app/CLI tests to return valid Today JSON - when prompt ID is `weather.today_generated_text`. +- Add or change the active Daily report ID to: + +```go +Daily ID = "daily" +``` + +- Remove active use of `DailyToday`. + - Prefer removing the exported `DailyToday` constant entirely if no active + code needs it. + - If temporary compile sequencing requires keeping it during this stage, + remove it before the stage is complete. +- Replace `dailyTodayDefinition` with `dailyDefinition`. +- Daily definition values: + - ID `Daily` + - name `Daily Report` + - prompt ID `weather.daily_generated_text` + - generation mode `GenerationModeGeneratedTextTemplate` + - template ID `daily` + - generated-text schema ID `daily` + - artifact group `daily` + - batch output name `daily.md` + - generated `true` + - compatible prior IDs `[]ID{Daily}` + - comparison strategy same valid local date + - no morning batch membership + - no evening batch membership +- Add `dailyModules()` with the module order from `docs/roadmap/daily.md`: + - `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` +- Add `resolveDaily` requiring `ResolveRequest.Date`. + - Return an actionable error when `Date` is zero. + - Resolve the date as a local civil day in `ResolveRequest.Location`. +- Update report name/config resolution: + - `IDForCommandName("daily")` returns `Daily`. + - `IDForConfigKey("daily")` returns `Daily`. + - `IDForConfigKey("daily_today")` returns an unknown config-key error. +- Update module registry supported-report lists: + - replace `report.DailyToday` with `report.Daily` for shared Daily-compatible + modules; + - add `report.Daily` to Daily planning support. +- Update Recent Changes dispatch where it currently groups daily-style reports, + replacing `DailyToday` with `Daily`. +- Ensure `BatchReports` continues to include Today in the morning batch and + Tomorrow in the evening batch, with no Daily membership. + +### Acceptance Criteria + +- `report.DefaultRegistry()` includes `daily` and not `daily_today`. +- `weatherreporter generate daily` resolves to report ID `daily`. +- `reports.daily` config overrides apply to Daily. +- `reports.daily_today` is rejected. +- Daily uses generated-text-template mode. +- Daily metadata, RunID, artifact paths, distributor variables, and report + output all use report ID/artifact group `daily`. +- Scheduled batches do not include Daily. + +### Tests + +- Update report tests for: + - registry membership; + - command-name resolution; + - config-key resolution; + - generated-text-template metadata; + - explicit-date valid period; + - missing-date resolver error; + - batch membership. +- Update module registry tests to prove every default Daily module is buildable. +- Update Recent Changes tests to use Daily snapshots instead of legacy + `daily_today` snapshots where applicable. +- Suggested focused command: + +```sh +go test ./internal/report ./internal/briefing ./internal/changes +``` + +### Prompt Size + +This is the first larger cutover stage. It is still suitable for one +implementation prompt if the agent works package by package and keeps tests +focused. If compile errors spread widely, split into: + +1. report ID/name/config resolution; +2. module registry and Recent Changes updates; +3. report tests and stale-symbol cleanup. + +## Stage 5: CLI And App Workflow Integration + +### Goal + +Make the public command `weatherreporter generate daily --date YYYY-MM-DD` +execute the full generated-text-template workflow and reject missing dates. ### Files To Inspect -- `internal/app/app.go` -- `internal/app/app_test.go` - `internal/cli/root.go` - `internal/cli/root_test.go` +- `internal/app/app.go` +- `internal/app/app_test.go` - `internal/state` - `internal/adapters/scriptorium` - `internal/adapters/distributor` -- `internal/config` - `examples/config.yml` -### Acceptance Criteria - -- `weatherreporter generate today` succeeds in tests through the generated-text - template path. -- `weatherreporter generate daily` still succeeds through the existing daily - path and does not produce Today identity artifacts. -- `weatherreporter generate today --date YYYY-MM-DD` resolves that local civil - day. -- Morning batch uses Today artifacts and `today.md` output copy names. -- Notification debug artifacts record Today report ID, pipeline ID, bundle ID, - and bundle paths. -- Optional `--out` and batch `--out-dir` behavior remains unchanged except for - the new Today output name in morning batch. -- No secret values appear in CLI output, metadata, or notification artifacts. - -### Tests - -Add or update tests for: - -- CLI parser support for `generate today`. -- CLI parser proof that `generate daily` remains separate. -- CLI `--date` support for Today. -- App workflow artifacts for Today. -- App output copy behavior for Today. -- App workflow proof that Daily still produces existing daily identity. -- Batch output directory using `today.md`. -- Distributor request values for Today. -- Inspect commands loading Today run metadata/modules/data package/sources. - -Run: - -```sh -go test ./internal/app ./internal/cli ./internal/state -go test ./internal/adapters/scriptorium ./internal/adapters/distributor -go test ./... -go run ./cmd/weatherreporter --help -git diff --check -``` - -Stage size: suitable for one implementation prompt. - -## Stage 5: Documentation And Examples - -Goal: update implemented docs and maintained examples after the code exists. - ### Implementation -Update non-roadmap docs to describe implemented behavior only: - -- `docs/cli.md`: - - add `generate today`; - - keep `generate daily` documented as a separate command; - - document `--date` for Today generation; - - keep Daily docs accurate for the existing command. -- `docs/config.md`: - - document `reports.today`; - - keep `reports.daily` / `reports.daily_today` documentation separate while - the existing daily report remains implemented. -- `docs/operations.md`: - - update morning batch behavior; - - document Today artifact paths; - - update distributor identity examples if present. -- `docs/templates.md`: - - document Today template variables. -- `docs/internal/report-registry.md`: - - document Today report identity and its independence from Daily Today. -- `docs/internal/generatedtext.md`: - - document Today generated-text schema and validation. -- `docs/internal/reporttemplate.md`: - - document Today template/schema/prompt assets. -- `docs/internal/module.md`: - - document `today_planning`. -- `docs/internal/app-orchestration.md`: - - document Today only where the generic generated-text-template workflow does - not already cover it. -- `examples/config.yml`: - - add Today module override examples only if useful; - - keep existing daily examples accurate if they remain; - - keep no raw secrets. - -Roadmap docs: - -- Keep future Daily rewrite work only under `docs/roadmap/`. -- Do not document the future Daily rewrite outside roadmap docs. +- Update CLI date policy: + - `generate daily` requires `--date YYYY-MM-DD`; + - missing `--date` returns a concise actionable error; + - malformed `--date` remains an error; + - `generate today` keeps its current behavior; + - `generate tomorrow` remains date-free. +- Ensure `--config`, `--units`, `--tz`, `--out`, and distributor notification + behavior continue to work as they do for other generated-text-template + reports. +- Update app generated-text dispatch so Daily uses: + - prompt ID `weather.daily_generated_text`; + - schema ID `daily`; + - template ID `daily`; + - `BuildDailyRenderContext`. +- Ensure persisted artifacts include: + - raw generated text JSON; + - generated-text run result; + - normalized generated text; + - render context; + - rendered Markdown; + - metadata; + - optional output copy. +- Ensure distributor upload, when enabled, uses the managed Daily Markdown + report path and Daily template variables. ### Acceptance Criteria -- Non-roadmap docs describe Today as implemented and distinct from Daily. -- Non-roadmap docs do not imply `today` and `daily` are aliases. -- Maintained examples load successfully. -- CLI examples match actual `--help` output and parser behavior. -- Documentation follows `docs/policy/documentation.md`. +- `weatherreporter generate daily --date YYYY-MM-DD` runs through the + generated-text-template path. +- `weatherreporter generate daily` without `--date` fails before generation. +- `weatherreporter generate daily --date bad-date` fails before generation. +- Existing Today, Tomorrow, Hourly, Three-Day, Weekend, and Storm commands keep + their current syntax. +- Daily app workflow saves the same classes of artifacts as Today/Tomorrow. +- Daily optional `--out` copy behavior remains separate from the managed report + path. + +### Tests + +- Update CLI parser tests for: + - required Daily date; + - malformed Daily date; + - valid Daily date; + - Today and Tomorrow date behavior unchanged. +- Add or update app workflow tests for: + - Daily generated-text Scriptorium request; + - Daily schema validation; + - Daily render context persistence; + - Daily rendered report path; + - Daily optional output copy; + - Daily distributor request values when notification is enabled. +- Suggested focused command: + +```sh +go test ./internal/cli ./internal/app ./internal/state +``` + +### Prompt Size + +Medium. Suitable for one implementation prompt after Stages 1-4 compile. + +## Stage 6: Legacy DailyToday Sweep + +### Goal + +Remove stale active-code references to the legacy `daily_today` report after the +new Daily path is working. + +### Files To Inspect + +- `internal/report` +- `internal/briefing` +- `internal/config` +- `internal/app` +- `internal/changes` +- `internal/promptinput` +- `internal/state` +- `internal/generatedtext` +- `internal/reporttemplate` +- package tests + +### Implementation + +- Remove remaining production-code references to: + - `DailyToday`; + - `daily_today`; + - `weather.daily_report` on the active Daily path. +- Update test fixtures and helper names that represent the active Daily report. +- Keep references only when intentionally describing historical artifacts in + roadmap text. +- Do not add migration logic for old workspace files. +- Do not keep `daily_today` as a hidden alias. + +### Acceptance Criteria + +- `rg -n "DailyToday|daily_today|weather.daily_report" internal examples docs` + has no production-code or implemented-doc matches, except future/historical + roadmap references if intentionally retained. +- All report and module defaults refer to active report IDs. +- Tests no longer assume `daily` resolves to `daily_today`. + +### Tests + +- Run: + +```sh +rg -n "DailyToday|daily_today|weather.daily_report" internal examples docs +go test ./internal/... +``` + +### Prompt Size + +Small to medium. This can be combined with Stage 5 only if the agent has enough +context and compile errors are already localized. + +## Stage 7: Documentation And Examples + +### Goal + +Update implemented documentation and maintained examples after the Daily feature +exists. Keep planned or deferred behavior only under `docs/roadmap/`. + +### Files To Inspect + +- `README.md` +- `docs/cli.md` +- `docs/config.md` +- `docs/operations.md` +- `docs/templates.md` +- `docs/troubleshooting.md` +- `docs/internal/report-registry.md` +- `docs/internal/generatedtext.md` +- `docs/internal/reporttemplate.md` +- `docs/internal/module.md` +- `docs/internal/app-orchestration.md` +- `examples/config.yml` +- tests that load examples + +### Implementation + +- Update `docs/cli.md`: + - document `weatherreporter generate daily --date YYYY-MM-DD`; + - describe missing date as an error; + - keep Today and Tomorrow documented as separate commands. +- Update `docs/config.md`: + - document `reports.daily` module overrides; + - remove active `reports.daily_today` references. +- Update `docs/operations.md`: + - document Daily as manually targeted by date; + - document Daily artifact paths and managed-report behavior. +- Update `docs/templates.md`: + - document Daily template variables and generated-text fields. +- Update internal docs: + - report registry Daily identity; + - generated-text Daily validation; + - reporttemplate Daily assets; + - `daily_planning` module; + - app orchestration only where Daily differs from generic + generated-text-template flow. +- Update `examples/config.yml` only if it includes report module override + examples that should reference `daily`. +- Do not describe scheduled Daily behavior, old artifact migration, or future + template divergence as implemented behavior. + +### Acceptance Criteria + +- Non-roadmap docs describe only implemented Daily behavior. +- No implemented docs describe `daily_today` as an active report. +- Examples use implemented report config keys only. +- README remains concise and links to canonical docs instead of duplicating + reference material. ### Tests And Checks -Run: - ```sh -go test ./internal/config ./internal/cli ./internal/app -go test ./... -go run ./cmd/weatherreporter --help +go test ./internal/config ./internal/cli git diff --check +rg -n "daily_today|weather.daily_report|DailyToday" README.md docs examples ``` -Manual checks: +Review any remaining matches manually. Roadmap references may remain only when +they are clearly historical or future planning context. -```sh -rg -n "today.*alias|daily.*alias|daily_today.*retired|replace.*daily_today" README.md docs examples internal -``` +### Prompt Size -Expected remaining matches should be limited to roadmap discussion that clearly -states there is no aliasing in this feature. +Medium. Suitable for one implementation prompt after code behavior exists. -Stage size: suitable for one implementation prompt. +## Stage 8: Final Validation -## Stage 6: Final Validation And Stale-Symbol Sweep +### Goal -Goal: confirm Today is fully implemented as a separate report and no accidental -Daily/Today aliasing remains. +Verify the complete Daily cutover and catch stale references or documentation +drift. -### Required Validation - -Run: - -```sh -go test ./... -go run ./cmd/weatherreporter --help -git diff --check -``` - -Run focused package checks: +### Required Commands ```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 ./internal/state ./internal/promptinput ./internal/changes -go test ./internal/adapters/distributor ./internal/adapters/scriptorium ./internal/adapters/weatherapi +go test ./... +go run ./cmd/weatherreporter --help +git diff --check ``` -Run stale/alias checks: +### Stale Reference Checks ```sh -rg -n "IDForCommandName\\(\"daily\"\\).*Today|IDForConfigKey\\(\"daily\"\\).*Today" internal -rg -n "weather.today_generated_text|today.md|report.Today" internal docs examples +rg -n "DailyToday|daily_today|weather.daily_report" internal examples README.md docs +rg -n "reports\\.daily_today|weatherreporter generate daily(?!.*--date)" docs examples ``` -Manual review: +The second command uses a regex feature that may not be supported by every +`rg` build. If it fails, use simpler searches: -- `generate today` is listed in help and docs. -- `generate daily` remains listed separately. -- `generate daily` does not resolve to report ID `today`. -- `reports.daily` and `reports.today` are distinct config override keys. -- Morning batch output includes `today.md`. -- Today data package and metadata use report ID `today`. -- Distributor request values use `today`. -- Existing manual Daily behavior remains available. -- Existing Tomorrow behavior is unchanged. +```sh +rg -n "reports\\.daily_today|weatherreporter generate daily" docs examples +``` -Stage size: suitable for one implementation prompt. +Review remaining matches manually. + +### Manual Review Items + +- Confirm `weatherreporter --help` lists `daily`, `today`, and `tomorrow` + distinctly. +- Confirm `generate daily` help or parser behavior makes `--date` required. +- Confirm morning and evening batch definitions did not change except where + tests explicitly prove intended behavior. +- Confirm distributor template variables for Daily use report ID/artifact group + `daily`. +- Confirm old workspace artifacts are not migrated or rewritten. ## Deferred Work -Do not include these in the Today implementation: +Do not include these in the Daily replacement implementation: -- Rewriting the `daily` command/report in Today/Tomorrow style. -- Removing or retiring the existing `daily_today` report. -- Making `daily` an alias for `today`. -- Making `today` an alias for `daily`. -- Migrating historical `daily_today` workspace artifacts. -- Adding an inspection compatibility layer that rewrites old metadata IDs. -- Changing Tomorrow template/schema behavior except where shared helpers require - tests to be adjusted. -- Changing Distributor adapter behavior beyond Today template values. +- scheduling Daily in morning or evening batches; +- migration of old `daily_today` workspace artifacts; +- compatibility alias support for `daily_today`; +- changing Today or Tomorrow semantics; +- adding a generic report-template inheritance system; +- consolidating Daily and Tomorrow public generated-text types; +- making Daily default to today or tomorrow when `--date` is omitted; +- changing Scriptorium prompt registration behavior, which remains out of band. ## Open Questions No open questions block implementation. -The future relationship between `daily`, `daily_today`, and `today` is -explicitly deferred to the next Daily rewrite roadmap. For this implementation, -the required behavior is that Today and Daily remain separate commands and -separate report IDs. +The roadmap intentionally chooses the clean-break option for all previously +ambiguous areas: `daily_today` is removed from active behavior, `--date` is +required, Daily is not scheduled, and Daily owns separate template/schema/prompt +and planning-module surfaces even when they initially match Tomorrow. + +## Global Validation Checklist + +- `go test ./...` passes. +- `go run ./cmd/weatherreporter --help` is accurate. +- `git diff --check` passes. +- `weatherreporter generate daily --date YYYY-MM-DD` is the only valid Daily + generation form. +- `weatherreporter generate daily` without `--date` fails. +- `reports.daily` is accepted. +- `reports.daily_today` is rejected. +- No active code path uses `daily_today`. +- Daily generated reports use `weather.daily_generated_text`. +- Daily rendered Markdown uses the Daily template. +- Daily generated-text JSON uses the Daily schema. +- Daily data packages include `daily_planning`, not `tomorrow_planning`. +- Daily is absent from morning and evening scheduled batches. +- Non-roadmap documentation describes only implemented behavior.