425 lines
15 KiB
Markdown
425 lines
15 KiB
Markdown
# Today Report Roadmap
|
|
|
|
## Purpose
|
|
|
|
This roadmap defines the target state and implementation work needed to add a
|
|
new independent generated-text-template `today` report.
|
|
|
|
The report is not implemented yet. Current report behavior remains documented
|
|
outside `docs/roadmap/`.
|
|
|
|
## Intent
|
|
|
|
Today should be an independent generated-text-template report focused on the
|
|
current local civil day. It should mirror the implemented Tomorrow Report
|
|
structure, but its valid period, identity, prompt, template, schema, workspace
|
|
paths, distributor identity, and deterministic planning module should use
|
|
`today`.
|
|
|
|
This is a clean, separate report addition:
|
|
|
|
- `today` becomes a new canonical current-day generated-text report ID.
|
|
- The existing `daily_today` report remains independent for now.
|
|
- The existing public `daily` command remains independent for now.
|
|
- `weatherreporter generate today` and `weatherreporter generate daily` must
|
|
not be aliases for each other.
|
|
- Morning batch should use `today`, not `daily_today`.
|
|
- New Today artifacts use the `today` artifact group and report ID.
|
|
- Existing historical `daily_today` workspace artifacts do not need migration.
|
|
|
|
The next planned feature will rewrite the `daily` command/report in the same
|
|
style as Today and Tomorrow. Do not pre-solve that future work in this roadmap.
|
|
|
|
## Locked Decisions
|
|
|
|
- `today` is independent of `daily_today`.
|
|
- `generate today` is independent of `generate daily`.
|
|
- No command compatibility aliases between `today` and `daily`.
|
|
- No config-key compatibility aliases between `reports.today` and
|
|
`reports.daily` / `reports.daily_today`.
|
|
- Morning batch includes `today`.
|
|
- Morning batch should not include `daily_today` once Today is implemented.
|
|
- `today` needs its own deterministic planning module analogous to
|
|
`TomorrowPlanning`.
|
|
- Add a new public `generate today` command.
|
|
- Do not reuse the Tomorrow prompt, template, schema, report ID, artifact group,
|
|
or planning stanza for Today.
|
|
- Do not attempt to migrate old workspace artifacts.
|
|
|
|
## Target Report Shape
|
|
|
|
Today should render from deterministic current-day facts plus structured prose
|
|
from Scriptorium:
|
|
|
|
```markdown
|
|
# Today's Weather
|
|
|
|
**Forecast date:** Friday, May 29, 2026
|
|
**Updated:** Friday, May 29, 2026 at 8:30 AM
|
|
|
|
<GeneratedText summary>
|
|
|
|
## Daypart Forecast
|
|
|
|
- **Morning:** <deterministic daypart line>
|
|
- **Midday:** <deterministic daypart line>
|
|
- **Afternoon:** <deterministic daypart line>
|
|
- **Evening:** <deterministic daypart line>
|
|
|
|
## Precipitation Timing
|
|
|
|
- **10:00 AM** to **1:00 PM**: Precipitation is expected during this period.
|
|
The peak precipitation chance is 70% at 11:00 AM.
|
|
- <optional GeneratedText precipitation_timing>
|
|
|
|
## Forecast Discussion
|
|
|
|
<GeneratedText forecast_discussion paragraphs>
|
|
```
|
|
|
|
The precipitation section should render only when precipitation windows exist
|
|
for the current-day valid period. The deterministic daypart forecast should
|
|
follow the same module-driven presentation approach used by Tomorrow.
|
|
|
|
The title should be stable and explicit: `Today's Weather`.
|
|
|
|
## Report Identity
|
|
|
|
Add a report definition with:
|
|
|
|
- report ID: `today`
|
|
- public generate command: `today`
|
|
- prompt ID: `weather.today_generated_text`
|
|
- generation mode: `generated_text_template`
|
|
- template ID: `today`
|
|
- generated-text schema ID: `today`
|
|
- artifact group: `today`
|
|
- batch output name: `today.md`
|
|
- prior compatibility: Today only
|
|
- comparison strategy: same valid local date
|
|
- valid period: current local civil day in the effective report timezone,
|
|
`[00:00, next 00:00)`
|
|
|
|
Keep the existing `daily_today` report definition independent unless the future
|
|
Daily rewrite roadmap removes or replaces it.
|
|
|
|
Command and config resolution must remain distinct:
|
|
|
|
- `generate today` resolves to report ID `today`.
|
|
- `generate daily` resolves to the existing daily report ID.
|
|
- `reports.today` config overrides apply only to report ID `today`.
|
|
- `reports.daily` and `reports.daily_today` config overrides continue to apply
|
|
only to the existing daily report while that report exists.
|
|
|
|
## Batch Behavior
|
|
|
|
Morning batch should include Today in the position currently occupied by Daily
|
|
Today.
|
|
|
|
Target morning order:
|
|
|
|
1. `today`
|
|
2. `three_day`
|
|
3. `weekend`, when existing weekend rules include it
|
|
|
|
Existing Sunday behavior should remain equivalent except with Today replacing
|
|
Daily Today in the batch: scheduled Sunday morning should include `today` and
|
|
`three_day`, and should skip `weekend`.
|
|
|
|
Evening batch behavior is unchanged and should continue to include `tomorrow`.
|
|
Hourly remains excluded from scheduled batches unless a later roadmap changes
|
|
that.
|
|
|
|
The existing `daily` command/report may remain available for manual generation,
|
|
but it is no longer the morning batch current-day product once Today is
|
|
implemented.
|
|
|
|
## GeneratedText Contract
|
|
|
|
Today 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 for the source prompt text if prompt assets are
|
|
maintained locally:
|
|
|
|
- `internal/reporttemplate/prompts/today.generated_text.md`
|
|
|
|
Scriptorium registration remains out of band. Weatherreporter should invoke the
|
|
Today prompt by prompt ID and pass the data package as it does for other
|
|
generated-text reports.
|
|
|
|
## Template Context
|
|
|
|
Add dedicated Today types under `internal/generatedtext`, rather than reusing
|
|
Tomorrow types directly. The shape should mirror Tomorrow so template behavior
|
|
stays explicit and testable:
|
|
|
|
```go
|
|
type TodayRenderContext struct {
|
|
Report TodayReportContext
|
|
GeneratedText Today
|
|
Modules TodayTemplateModules
|
|
Collected facts.CollectedFacts
|
|
Derived facts.DerivedFacts
|
|
}
|
|
```
|
|
|
|
`TodayReportContext` should include:
|
|
|
|
- `Title`, exactly `Today's Weather`
|
|
- `ForecastDate`
|
|
- `ForecastDateLabel`, for example `Friday, May 29, 2026`
|
|
- `ForecastDayName`, for example `Friday`
|
|
- `GeneratedAt`
|
|
- `GeneratedAtLabel`
|
|
- `ValidPeriod`
|
|
- `Timezone`
|
|
|
|
`TodayTemplateModules` should expose the categories the Today template needs:
|
|
|
|
- `Metadata`
|
|
- `CurrentConditions`
|
|
- `HourlyForecast`
|
|
- `DerivedDailySummary`
|
|
- `DerivedDaypartSummaries`
|
|
- ordered daypart rows
|
|
- `PrecipTiming`
|
|
- `AlertDigest`
|
|
- `SPCConvectiveOutlooks`
|
|
- `AreaForecastDiscussion`
|
|
- `SPCConvectiveDiscussion`
|
|
- `WeatherStory`
|
|
- `TodayPlanning`
|
|
|
|
Today may share private helper functions with Tomorrow render-context
|
|
construction when the helper represents identical mechanics, such as snapshot
|
|
lookup or daypart row ordering. Do not expose Tomorrow-specific types through
|
|
the Today template context.
|
|
|
|
## Module Composition
|
|
|
|
The default module composition should mirror Tomorrow where the same facts are
|
|
useful for the current-day report, with a Today-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`
|
|
- `hourly_forecast`
|
|
- `today_planning`
|
|
|
|
Keep module outputs deterministic and prompt-facing. Do not add prose-only Go
|
|
fields unless the template needs a structured fact that cannot be expressed from
|
|
existing module data.
|
|
|
|
## Today Planning Module
|
|
|
|
Add a Today-specific deterministic planning module:
|
|
|
|
- module ID: `today_planning`
|
|
- stanza name: `today_planning`
|
|
- options type: `TodayPlanningOptions`
|
|
- output type: `TodayPlanningModule`
|
|
- supported report: `today`
|
|
|
|
The module should be analogous to `TomorrowPlanning`, but current-day oriented.
|
|
It should not reuse the public `TomorrowPlanningModule` type or
|
|
`tomorrow_planning` stanza.
|
|
|
|
Recommended initial fields:
|
|
|
|
- `morning_readiness`
|
|
- `commute_school_workday_concerns`
|
|
- `outdoor_planning`
|
|
- `late_day_change_watch`
|
|
|
|
The exact field names may be adjusted during implementation if tests and docs
|
|
make a better shape clear, but the module must remain deterministic and
|
|
current-day specific. Private helper functions may be shared with Tomorrow
|
|
planning when the underlying logic is truly identical.
|
|
|
|
## Implementation Plan
|
|
|
|
1. Add Today report identity.
|
|
- Add `report.Today`.
|
|
- Keep the existing `report.DailyToday` active for now.
|
|
- Add command-name support for `today`.
|
|
- Do not change the `daily` command mapping in this roadmap.
|
|
- Add config-key support for `today`.
|
|
- Do not change `reports.daily` or `reports.daily_today` mapping in this
|
|
roadmap.
|
|
- Add a report definition with generated-text-template identity fields.
|
|
- Add current-local-civil-day valid-period resolution.
|
|
- Update report tests for ID, prompt ID, artifact group, command mapping,
|
|
config key mapping, batch order, and valid period.
|
|
|
|
2. Add Today planning module.
|
|
- Add `module.TodayPlanning`.
|
|
- Add `TodayPlanningOptions`.
|
|
- Add `TodayPlanningModule` and builder under `internal/briefing`.
|
|
- Register it in the default module registry for `report.Today`.
|
|
- Add tests for output shape, supported report, unsupported reports, and
|
|
empty/fallback behavior.
|
|
|
|
3. Add Today generated-text validation and schema.
|
|
- Add `generatedtext.Today`.
|
|
- Add `ValidateToday`.
|
|
- Add `today.generated_text.schema.json`.
|
|
- Add generated-text validation tests matching Tomorrow coverage.
|
|
|
|
4. Add Today template and render context.
|
|
- Add `today.md.tmpl`.
|
|
- Add `TodayRenderContext`, `TodayReportContext`, and
|
|
`TodayTemplateModules`.
|
|
- Add `BuildTodayRenderContext`.
|
|
- Use the internal snapshot lookup helper for module extraction.
|
|
- Add render-context and template tests for populated and omitted optional
|
|
modules.
|
|
|
|
5. Register Today in generated-text and embedded asset catalogs.
|
|
- Add a generated-text catalog entry.
|
|
- Add reporttemplate template/schema map entries if the current asset
|
|
lookup still uses explicit maps.
|
|
- Extend catalog completeness tests.
|
|
- Add unsupported schema/template combination coverage if needed.
|
|
|
|
6. Integrate app, CLI, config, batches, and distributor workflows.
|
|
- Ensure `weatherreporter generate today` resolves and runs through the
|
|
generated-text-template workflow.
|
|
- Ensure `weatherreporter generate daily` remains the existing daily
|
|
workflow and does not resolve to Today.
|
|
- Ensure morning batch uses `today` instead of `daily_today`.
|
|
- Persist raw generated text, structured run result, normalized generated
|
|
text, render context, Markdown report, metadata, and optional output copy.
|
|
- Ensure distributor notification uses the managed Today Markdown report
|
|
path and Today template values.
|
|
- Ensure report metadata, RunID, artifact paths, data-package paths, batch
|
|
output names, and distributor template variables use `today`.
|
|
|
|
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 Today behavior after
|
|
the code changes land.
|
|
- Keep `daily` and `today` documented as distinct commands/reports.
|
|
|
|
## Test Plan
|
|
|
|
Add or update tests for:
|
|
|
|
- report registry membership for both `today` and existing `daily_today`
|
|
- `today` command-name resolution to `today`
|
|
- `daily` command-name resolution remaining independent from `today`
|
|
- config-key resolution for `reports.today`
|
|
- config-key resolution for `reports.daily` and `reports.daily_today`
|
|
remaining independent from `reports.today`
|
|
- morning batch order with `today`, `three_day`, and conditional `weekend`
|
|
- Sunday morning batch skip behavior with `today`
|
|
- current-day valid period in the configured timezone
|
|
- 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, Today
|
|
planning extraction, and daypart ordering
|
|
- Today planning module output and supported-report validation
|
|
- app workflow artifacts for `generate today`
|
|
- `generate daily` remains separate from `generate today`
|
|
- optional `--out` copy behavior
|
|
- distributor template values and managed report notification source
|
|
- CLI parser support for `generate today`
|
|
- config report module overrides for `reports.today`
|
|
|
|
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 today` and keep `generate daily`
|
|
documented as a separate existing command.
|
|
- `docs/config.md`: document `reports.today` module overrides separately from
|
|
existing daily report overrides.
|
|
- `docs/operations.md`: document Today artifact paths, morning batch behavior,
|
|
and distributor upload identity.
|
|
- `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 behavior.
|
|
- `docs/internal/reporttemplate.md`: document Today template assets.
|
|
- `docs/internal/module.md`: document `today_planning`.
|
|
- `docs/internal/app-orchestration.md`: document Today workflow only if it
|
|
differs from the generic generated-text-template flow.
|
|
|
|
## Ambiguities Addressed
|
|
|
|
- Independence: `today` is separate from `daily_today`; it does not replace the
|
|
existing report definition in this roadmap.
|
|
- Command behavior: `generate today` and `generate daily` are not aliases.
|
|
- Config behavior: `reports.today` is not an alias for `reports.daily` or
|
|
`reports.daily_today`.
|
|
- Batch behavior: morning batch includes `today` instead of `daily_today`.
|
|
- Planning module: Today has its own deterministic planning module.
|
|
- Artifact identity: new Today artifacts and distributor values use `today`.
|
|
- 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:
|
|
|
|
- How the future rewritten `daily` command/report should relate to `today`.
|
|
- Whether the future Daily rewrite removes or retires `daily_today`.
|
|
- Whether old `daily_today` workspace artifacts should ever receive a migration
|
|
or inspection compatibility layer.
|