Remove completed roadmap cleanup plans

This commit is contained in:
2026-06-15 12:52:18 +00:00
parent cd8d77b37c
commit 67b30dbad6
7 changed files with 25 additions and 1975 deletions

View File

@@ -1,441 +0,0 @@
# Tomorrow Report Implementation Roadmap
## Purpose
This roadmap defines the staged implementation plan for
`docs/roadmap/tomorrow.md`. It is written for an LLM coding agent that will
implement each stage in order. The conceptual target state, user intent, and
locked product decisions live in `docs/roadmap/tomorrow.md`; this file defines
the concrete implementation sequence.
This is future-work planning. Do not treat the behavior described here as
implemented until the corresponding code, tests, examples, and non-roadmap docs
are updated.
## Implementation Guardrails
- Preserve public CLI syntax: `weatherreporter generate tomorrow`.
- Make a clean pre-release break from report ID `daily_tomorrow`; do not add
compatibility aliases.
- Keep report identity, prompt IDs, template IDs, artifact groups, output names,
and comparison policy centralized in `internal/report`.
- Reuse the existing `generated_text_template` workflow implemented for Hourly.
- Keep Scriptorium details behind the existing adapter boundary.
- Keep Go responsible for deterministic facts, valid periods, module snapshots,
structured generated-text validation, and final Markdown template rendering.
- Keep templates responsible for wording and layout.
- Keep generated JSON schemas and Markdown templates as embedded asset files,
not inline Go strings.
- Preserve current managed artifact behavior except where report identity
intentionally changes from `daily_tomorrow` to `tomorrow`.
## Stage 1: Report Identity Split
Goal: make Tomorrow an independent report ID and artifact identity while
preserving the public `generate tomorrow` command.
Implementation:
- Replace `report.DailyTomorrow` with `report.Tomorrow` whose value is
`"tomorrow"`.
- Rename report-definition helpers and resolvers around the new identity:
`dailyTomorrowDefinition` to `tomorrowDefinition`,
`dailyTomorrowModules` to `tomorrowModules`, and
`resolveDailyTomorrow` to `resolveTomorrow`.
- Update `report.DefaultRegistry`, `Registry.All`, batch resolution, and tests
so the built-in report order contains `tomorrow` instead of
`daily_tomorrow`.
- Update `internal/app` so `app.ReportTomorrow` resolves to `report.Tomorrow`.
- Keep the valid period as the next local civil day.
- Keep evening batch behavior: `run evening` should still generate the Tomorrow
report.
- Change Tomorrow definition identity fields to:
- `ID: report.Tomorrow`
- `Name: "Tomorrow Report"`
- `ArtifactGroup: "tomorrow"`
- `BatchOutputName: "tomorrow.md"`
- `Generated: true`
- `CompatiblePriorIDs: []report.ID{report.Tomorrow}`
- `ComparisonStrategy: report.CompareSameValidDate`
- Keep the current Tomorrow module composition initially, renamed to
`tomorrowModules`, so the prompt data package continues to include the
daypart, precipitation, alert, SPC, AFD, weather story, tomorrow planning,
and hourly facts already available.
- Update all code and tests that assert `daily_tomorrow` paths, metadata,
RunIDs, prior compatibility, or registry IDs.
Acceptance criteria:
- No production-code references to `report.DailyTomorrow` or report ID
`daily_tomorrow` remain.
- `weatherreporter generate tomorrow` still parses and resolves successfully.
- Evening batch contains `tomorrow`.
- Managed workspace artifact paths and distributor identity values now use
`tomorrow`.
Suggested validation:
```bash
go test ./internal/report ./internal/app ./internal/cli ./internal/state
```
This stage is suitable for one implementation prompt.
## Stage 2: Tomorrow GeneratedText Contract
Goal: add structured Tomorrow LLM output validation and schema assets.
Implementation:
- Add `internal/generatedtext/tomorrow.go` with:
```go
type Tomorrow struct {
Summary string `json:"summary"`
ForecastDiscussion []string `json:"forecast_discussion"`
PrecipitationTiming string `json:"precipitation_timing,omitempty"`
Confidence string `json:"confidence,omitempty"`
}
```
- Add `generatedtext.ValidateTomorrow`.
- Use `json.Decoder.DisallowUnknownFields`.
- Reject multiple JSON values.
- Trim `Summary`, `PrecipitationTiming`, `Confidence`, and each
`ForecastDiscussion` paragraph.
- Drop blank discussion paragraphs after trimming, then require at least one
remaining paragraph.
- Reject blank `Summary`.
- Return normalized JSON with the same public field names.
- Add `internal/reporttemplate/schemas/tomorrow.generated_text.schema.json`.
The schema should:
- require `summary`;
- require `forecast_discussion`;
- define `forecast_discussion` as an array of strings with at least one item;
- allow optional `precipitation_timing` and `confidence`;
- reject additional properties.
- Add `internal/reporttemplate/prompts/tomorrow.generated_text.md` as the
maintained Scriptorium prompt source asset. This file is a source contract for
out-of-band Scriptorium prompt registration; weatherreporter does not need to
load prompt Markdown at runtime.
- Add Tomorrow to `internal/reporttemplate` schema lookup.
- Update app generated-text validation dispatch so it can return either
`generatedtext.Hourly` or `generatedtext.Tomorrow`. Prefer a small generic
dispatch shape such as:
```go
func validateGeneratedText(def report.Definition, data []byte) (any, []byte, error)
```
Then type-check the returned value in render-context dispatch.
Acceptance criteria:
- Tomorrow generated text rejects unknown fields, missing required fields,
blank summary, and no usable forecast discussion paragraphs.
- Optional `precipitation_timing` and `confidence` are trimmed and omitted from
normalized JSON when empty.
- Hourly generated text behavior is unchanged.
Suggested validation:
```bash
go test ./internal/generatedtext ./internal/reporttemplate ./internal/app
```
This stage is suitable for one implementation prompt.
## Stage 3: Daypart Presentation Fields
Goal: add only the daypart fields needed to keep the Tomorrow template
composable without moving prose construction into Go.
Implementation:
- Extend the `derived_daypart_summaries` module output with presentation
helpers that are facts, not complete sentences:
- `display_name`, for example `Morning`;
- `dominant_condition_lower`, for inline template text;
- `temperature_phrase_f`, such as `low 70s`, `upper 60s`, or
`upper 60s to mid-70s`;
- `mention_precipitation`, true when max PoP is at or above the existing
hourly forecast precipitation mention threshold, currently 20%;
- `max_pop_time_label`, using friendly local hour format such as `8:00 AM`
when max PoP time exists.
- Reuse the existing hourly forecast precipitation mention threshold constant
rather than adding a user config field in this change.
- Keep existing structured numeric fields in the module output.
- Do not add a prewritten `daypart_line` string.
- Do not add wind prose in this stage unless tests show the initial template
needs a specific structured wind fact. If wind wording is needed, add a
small structured wind field, not a full sentence.
Acceptance criteria:
- Daypart module output has enough structured fields for a readable Tomorrow
template.
- The output remains useful for YAML prompt packages.
- No generated prose sentence is hard-coded into the module.
Suggested validation:
```bash
go test ./internal/briefing ./internal/promptinput
```
This stage is suitable for one implementation prompt.
## Stage 4: Tomorrow Render Context And Template
Goal: render Tomorrow Markdown from structured generated text, module outputs,
and report metadata.
Implementation:
- Add a dedicated Tomorrow render context under `internal/generatedtext`, for
example:
```go
type TomorrowRenderContext struct {
Report TomorrowReportContext
GeneratedText Tomorrow
Modules TomorrowTemplateModules
Collected facts.CollectedFacts
Derived facts.DerivedFacts
}
```
- Add `TomorrowReportContext` with:
- `Title`, for example `Sunday's Weather`;
- `ForecastDate`;
- `ForecastDateLabel`, for example `Sunday, June 15, 2026`;
- `ForecastDayName`, for example `Sunday`;
- `GeneratedAt`;
- `GeneratedAtLabel`, for example
`Saturday, June 14, 2026 at 9:14 AM`;
- `ValidPeriod`;
- `Timezone`.
- Construct `Title` in Go, not in the template.
- Add `TomorrowTemplateModules` with pointer fields for the module outputs used
by the template:
- `Metadata`;
- `DerivedDailySummary`;
- `DerivedDaypartSummaries`;
- `PrecipTiming`;
- `AlertDigest`;
- `SPCConvectiveOutlooks`;
- `AreaForecastDiscussion`;
- `SPCConvectiveDiscussion`;
- `WeatherStory`;
- `TomorrowPlanning`.
- Add an ordered daypart slice for the template, derived from the configured
daypart order rather than ranging directly over a map. This can live in
`TomorrowTemplateModules`, for example `Dayparts []TomorrowDaypartContext`.
- Add `BuildTomorrowRenderContext`.
- Add `internal/reporttemplate/templates/tomorrow.md.tmpl`.
- Add Tomorrow to `internal/reporttemplate` template lookup.
- Template shape:
- title;
- forecast date;
- generated timestamp;
- `GeneratedText.Summary`;
- deterministic `Daypart Forecast` bullets in configured order;
- conditional `Precipitation Timing` only when precipitation windows exist;
- deterministic precipitation window bullets before optional
`GeneratedText.PrecipitationTiming`;
- `Forecast Discussion` with one paragraph per
`GeneratedText.ForecastDiscussion` item.
- Keep current conditions and hourly forecast available through the data
package and render context, but do not render them in the initial Tomorrow
template unless the template explicitly uses them.
Acceptance criteria:
- The template renders without map-order nondeterminism.
- Precipitation Timing is omitted when no precipitation windows exist.
- Forecast Discussion supports multiple paragraphs.
- Missing optional modules produce clean omission or fallback behavior, not
template execution errors.
Suggested validation:
```bash
go test ./internal/generatedtext ./internal/reporttemplate ./internal/briefing
```
This stage is suitable for one implementation prompt.
## Stage 5: App Workflow Integration
Goal: route Tomorrow through the generated-text-template workflow end to end.
Implementation:
- Change Tomorrow report definition to:
- `PromptID: "weather.tomorrow_generated_text"`
- `GenerationMode: report.GenerationModeGeneratedTextTemplate`
- `TemplateID: "tomorrow"`
- `GeneratedTextSchemaID: "tomorrow"`
- Update `internal/app.buildRenderContext` dispatch:
- hourly template requires `generatedtext.Hourly`;
- tomorrow template requires `generatedtext.Tomorrow`;
- unsupported type/template combinations return actionable errors.
- Ensure Scriptorium `run` writes raw generated text to a `.json` path for
Tomorrow, matching the existing generated-text-template workflow.
- Ensure normalized generated text, render context JSON, generated Markdown,
metadata, and final report artifacts are persisted through existing state
helpers.
- Ensure app errors include report ID `tomorrow` and RunID context.
Acceptance criteria:
- `weatherreporter generate tomorrow` no longer invokes Scriptorium for full
Markdown.
- The workflow validates Scriptorium JSON output, builds a Tomorrow render
context, and renders Markdown locally.
- Hourly generated-text-template behavior remains unchanged.
Suggested validation:
```bash
go test ./internal/app ./internal/state ./internal/adapters/scriptorium
```
This stage is suitable for one implementation prompt.
## Stage 6: CLI, State, Distributor, And Batch Behavior
Goal: update cross-package behavior affected by the report ID clean break.
Implementation:
- Update CLI tests and command-output expectations for `generate tomorrow`.
- Update state/path tests so managed artifacts, snapshots, data packages,
generated-text artifacts, render contexts, and report files use artifact group
`tomorrow`.
- Update batch tests:
- evening batch emits report ID `tomorrow`;
- batch output copy name remains `tomorrow.md`;
- partial-failure behavior is unchanged.
- Update Recent Changes tests:
- Tomorrow compares only against prior `tomorrow` snapshots;
- Daily Today no longer treats Tomorrow as a compatible prior unless the
implementation explicitly keeps that relationship for Daily Today only.
- Update distributor notification tests so rendered template variables use:
- `report_id=tomorrow`;
- `artifact_group=tomorrow`;
- `batch_output_name=tomorrow.md`.
- Update config tests so report module overrides use `reports.tomorrow`.
Do not accept `reports.daily_tomorrow` unless a future explicit
compatibility decision reverses the clean break.
Acceptance criteria:
- Public CLI syntax is stable.
- Persisted artifacts and distributor request context use the new report ID.
- Batch behavior is unchanged except for the new ID.
- No tests rely on `daily_tomorrow`.
Suggested validation:
```bash
go test ./internal/cli ./internal/app ./internal/state ./internal/config ./internal/report
```
This stage is suitable for one implementation prompt.
## Stage 7: Documentation And Examples
Goal: align implemented docs and maintained examples after the code change.
Implementation:
- Update non-roadmap docs only after the behavior is implemented.
- Inspect and update:
- `docs/cli.md`;
- `docs/config.md`;
- `docs/operations.md`;
- `docs/troubleshooting.md`, if new failure modes are introduced;
- `docs/internal/report-registry.md`;
- `docs/internal/generatedtext.md`;
- `docs/internal/reporttemplate.md`;
- `docs/internal/state.md`;
- `docs/templates.md`;
- relevant Scriptorium and distributor integration docs only if their
weatherreporter-facing contract changed.
- Update `examples/config.yml` if it references Tomorrow modules or
`reports.daily_tomorrow`.
- Keep future Today/Daily split language only under `docs/roadmap/`.
- Do not document unimplemented Today or generic Daily products as current
behavior.
Acceptance criteria:
- Non-roadmap docs describe implemented behavior only.
- Docs use report ID `tomorrow`.
- Examples load under current config validation.
- No stale user-facing references to `daily_tomorrow` remain outside historical
roadmap context.
Suggested validation:
```bash
rg -n "daily_tomorrow|Daily Tomorrow|weather.daily_report" README.md docs examples internal
git diff --check
```
This stage is suitable for one implementation prompt.
## Stage 8: Final Validation
Goal: verify the completed cutover as a coherent behavior change.
Run:
```bash
go test ./internal/report ./internal/generatedtext ./internal/reporttemplate ./internal/briefing ./internal/app ./internal/cli ./internal/state
go test ./...
go run ./cmd/weatherreporter --help
git diff --check
```
Also run targeted stale-symbol checks:
```bash
rg -n "DailyTomorrow|dailyTomorrow|daily_tomorrow" internal docs examples
rg -n "weather.tomorrow_generated_text|TemplateID:.*tomorrow|GeneratedTextSchemaID:.*tomorrow" internal docs
```
Acceptance criteria:
- Full test suite passes.
- Help output still shows `generate tomorrow`.
- No production-code stale `daily_tomorrow` symbols remain.
- Generated-text-template artifacts for Tomorrow are persisted in the same
categories as Hourly.
- Existing Hourly behavior still passes tests.
This stage is suitable for one implementation prompt.
## Open Questions
None block implementation. The required decisions are locked by
`docs/roadmap/tomorrow.md` and this implementation plan:
- Tomorrow uses report ID `tomorrow`.
- Tomorrow uses prompt ID `weather.tomorrow_generated_text`.
- Tomorrow uses template ID and generated-text schema ID `tomorrow`.
- Tomorrow forecast discussion is an array of paragraph strings.
- `daily_tomorrow` compatibility aliases are intentionally not preserved.
## Global Validation Checklist
- `go test ./...`
- `go run ./cmd/weatherreporter --help`
- `git diff --check`
- `rg -n "DailyTomorrow|dailyTomorrow|daily_tomorrow" internal docs examples`
- Confirm `weatherreporter generate tomorrow` uses structured JSON from
Scriptorium and renders final Markdown locally.
- Confirm distributor notification context uses `report_id=tomorrow` and
`artifact_group=tomorrow`.
- Confirm examples contain no unimplemented fields and no secrets.