Add a feature roadmap and implementation plan for a new daily report
This commit is contained in:
434
docs/roadmap/daily.md
Normal file
434
docs/roadmap/daily.md
Normal file
@@ -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
|
||||
|
||||
<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:
|
||||
|
||||
```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.
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user