499 lines
16 KiB
Markdown
499 lines
16 KiB
Markdown
# Near-Term Report Implementation Roadmap
|
|
|
|
## Purpose
|
|
|
|
This roadmap defines the concrete implementation sequence for
|
|
`docs/roadmap/near-term.md`. It is written for an LLM coding agent that will
|
|
implement each stage in order.
|
|
|
|
This is a future-work roadmap. Until a stage is implemented, non-roadmap docs
|
|
must not describe `near_term` behavior as available.
|
|
|
|
## Source Feature Roadmap
|
|
|
|
Use `docs/roadmap/near-term.md` as the authoritative feature roadmap for user
|
|
intent, target behavior, and policy choices. This document is the implementation
|
|
plan. If the target behavior changes, update `near-term.md` first, then update
|
|
this roadmap.
|
|
|
|
## Locked Implementation Decisions
|
|
|
|
- Add report ID `near_term` and Go constant `report.NearTerm`.
|
|
- Add CLI command `weatherreporter generate near-term`.
|
|
- Do not add `--date`, `--start`, `--end`, or duration flags for this report.
|
|
- Do not add `near_term` to morning or evening batches in the first
|
|
implementation.
|
|
- Define the valid-period duration with a package-owned constant, initially
|
|
`6` hours.
|
|
- Resolve the valid period as `[generation_time, generation_time + 6h)` in the
|
|
effective report timezone.
|
|
- Use prompt ID `weather.near_term_report`.
|
|
- Use artifact group `near-term` and batch output name `near-term.md`.
|
|
- Add comparison strategy constant `CompareRollingWindow = "rolling_window"`.
|
|
- Declare `CompatiblePriorIDs: []report.ID{report.NearTerm}`, but do not emit
|
|
Recent Changes for `near_term` in the first implementation.
|
|
- Keep state prior lookup returning `nil` for rolling-window reports until a
|
|
future comparison algorithm is designed.
|
|
- Default module order is:
|
|
1. `metadata`
|
|
2. `current_conditions`
|
|
3. `hourly_forecast`
|
|
4. `precip_timing`
|
|
5. `alert_digest`
|
|
6. `spc_convective_outlooks`
|
|
7. `area_forecast_discussion`
|
|
8. `spc_convective_discussion`
|
|
9. `weather_story`
|
|
- Configure the near-term `area_forecast_discussion` module with only
|
|
`key_messages` and `short_term` sections.
|
|
- Do not include daily/daypart modules in the default near-term composition.
|
|
- Alert and SPC modules must use existing valid-period overlap behavior.
|
|
- Preserve existing public behavior for all current report types.
|
|
|
|
## Stage 1: Report Identity And Period Resolution
|
|
|
|
Goal: add the `near_term` report definition, constants, registry entry, and
|
|
rolling six-hour valid-period resolver.
|
|
|
|
Files to inspect:
|
|
|
|
- `internal/report/definition.go`
|
|
- `internal/report/registry.go`
|
|
- `internal/report/period.go`
|
|
- `internal/report/daily_report.go`
|
|
- `internal/report/period_test.go`
|
|
- `internal/state/filesystem.go`
|
|
|
|
Implementation:
|
|
|
|
- Add `NearTerm ID = "near_term"` in `internal/report/definition.go`.
|
|
- Add `CompareRollingWindow ComparisonStrategy = "rolling_window"`.
|
|
- Add `internal/report/near_term_report.go`.
|
|
- Define a package-local duration constant in that file, for example:
|
|
|
|
```go
|
|
const nearTermHours = 6
|
|
```
|
|
|
|
- Add `nearTermDefinition()` returning:
|
|
- `ID: NearTerm`
|
|
- `Name: "Near-Term Report"`
|
|
- `PromptID: "weather.near_term_report"`
|
|
- `ComparisonStrategy: CompareRollingWindow`
|
|
- `ArtifactGroup: "near-term"`
|
|
- `BatchOutputName: "near-term.md"`
|
|
- `Generated: true`
|
|
- `CompatiblePriorIDs: []ID{NearTerm}`
|
|
- `Modules: nearTermModules()`
|
|
- no `Morning` or `Evening` membership
|
|
- `resolve: resolveNearTerm`
|
|
- Implement `resolveNearTerm` as generation-time anchored:
|
|
|
|
```go
|
|
localNow := req.Now.In(req.Location)
|
|
return timeutil.Period{
|
|
Start: localNow,
|
|
End: localNow.Add(nearTermHours * time.Hour),
|
|
}, nil
|
|
```
|
|
|
|
- Add `nearTermDefinition()` to `DefaultRegistry()`.
|
|
- Add `NearTerm` to `Registry.All()` in a stable order after
|
|
`DailyTomorrow` and before `ThreeDay`.
|
|
- Do not change `BatchReports`.
|
|
- Leave `state.FindPriorSnapshot` behavior unchanged for
|
|
`CompareRollingWindow`; it should return `nil` because it only supports
|
|
same-date and weekend lookup.
|
|
|
|
Tests:
|
|
|
|
- Add report period tests for:
|
|
- lookup succeeds for `NearTerm`;
|
|
- `Registry.All()` includes `NearTerm`;
|
|
- fixed generation time resolves to exactly six hours;
|
|
- timezone-aware start and end use the effective location;
|
|
- valid period is not civil-day truncated;
|
|
- metadata RunID includes `near_term`;
|
|
- batch membership remains unchanged.
|
|
- Update registry metadata/path tests to include:
|
|
- artifact group `near-term`;
|
|
- batch output name `near-term.md`;
|
|
- generated `true`;
|
|
- compatible prior IDs `[]ID{NearTerm}`;
|
|
- comparison strategy `CompareRollingWindow`.
|
|
|
|
Validation:
|
|
|
|
```bash
|
|
go test ./internal/report ./internal/state
|
|
```
|
|
|
|
This stage is small enough for one implementation prompt.
|
|
|
|
## Stage 2: Module Compatibility And Default Composition
|
|
|
|
Goal: make existing modules compatible with `near_term` where appropriate and
|
|
declare the default module composition.
|
|
|
|
Files to inspect:
|
|
|
|
- `internal/report/near_term_report.go`
|
|
- `internal/briefing/modules.go`
|
|
- `internal/module/module.go`
|
|
- `internal/briefing/modules_test.go`
|
|
- `internal/briefing/base_modules_test.go`
|
|
- `internal/briefing/derived_modules_test.go`
|
|
|
|
Implementation:
|
|
|
|
- Add `nearTermModules()` in `internal/report/near_term_report.go`.
|
|
- Use explicit module items in this order:
|
|
- `module.Metadata`
|
|
- `module.CurrentConditions`
|
|
- `module.HourlyForecast`
|
|
- `module.PrecipTiming`
|
|
- `module.AlertDigest`
|
|
- `module.SPCConvectiveOutlooks`
|
|
- `module.AreaForecastDiscussion` with options:
|
|
|
|
```go
|
|
module.AreaForecastDiscussionOptions{
|
|
Sections: []string{"key_messages", "short_term"},
|
|
}
|
|
```
|
|
|
|
- `module.SPCConvectiveDiscussion`
|
|
- `module.WeatherStory`
|
|
- Expand module `SupportedReports` in `internal/briefing/modules.go`:
|
|
- include `report.NearTerm` in `allReports`;
|
|
- include `report.NearTerm` for `HourlyForecast`;
|
|
- do not include `report.NearTerm` for `NarrativeForecast`;
|
|
- do not include `report.NearTerm` in `daypartReports`;
|
|
- do not include `report.NearTerm` for `DerivedDailySummary`,
|
|
`DerivedDaypartSummaries`, `OutdoorWindows`, or `TomorrowPlanning`.
|
|
- Keep `PrecipTiming`, `AlertDigest`, `SPCConvectiveOutlooks`,
|
|
`AreaForecastDiscussion`, `SPCConvectiveDiscussion`, and `WeatherStory`
|
|
compatible through `allReports`.
|
|
- Do not add a new module ID in this stage.
|
|
|
|
Tests:
|
|
|
|
- Add or update module registry tests proving:
|
|
- default near-term composition validates;
|
|
- all default near-term modules have builders;
|
|
- daily/daypart-only modules reject `report.NearTerm`;
|
|
- `HourlyForecast` builds for `report.NearTerm`;
|
|
- AFD options for the near-term default include only key messages and short
|
|
term.
|
|
- Add a focused AFD module test that near-term options omit long term when the
|
|
source provides it.
|
|
|
|
Validation:
|
|
|
|
```bash
|
|
go test ./internal/report ./internal/briefing ./internal/module
|
|
```
|
|
|
|
This stage is small enough for one implementation prompt.
|
|
|
|
## Stage 3: Derived Facts For Rolling Windows
|
|
|
|
Goal: teach `internal/facts` to build the facts needed by the near-term module
|
|
set without requiring daily summaries or daypart summaries.
|
|
|
|
Files to inspect:
|
|
|
|
- `internal/facts/facts.go`
|
|
- `internal/facts/facts_test.go`
|
|
- `internal/forecast`
|
|
- `internal/timeutil`
|
|
- `internal/briefing/modules.go`
|
|
|
|
Implementation:
|
|
|
|
- Add `report.NearTerm` handling in `facts.BuildDerived`.
|
|
- For near-term:
|
|
- populate `ValidPeriodHourlyPeriods` from the resolved six-hour valid
|
|
period;
|
|
- populate `ValidPeriodNarrativePeriods` if the existing generic selection
|
|
already does so, but do not require it for default near-term modules;
|
|
- build `PrecipTiming` from `ValidPeriodHourlyPeriods`;
|
|
- select alert overlaps using the near-term valid period;
|
|
- select SPC outlooks and discussions using the near-term valid period;
|
|
- do not build or require `DailySummaries`;
|
|
- do not build or require `DaypartSummaries`;
|
|
- do not build `StormWindowSummary`.
|
|
- Preserve existing daily, tomorrow, three-day, weekend, and storm derivation.
|
|
- If any existing helper assumes civil-day coverage, keep near-term on the
|
|
generic valid-period hourly path instead of reusing that helper.
|
|
|
|
Tests:
|
|
|
|
- Add facts tests for:
|
|
- valid-period hourly selection over a rolling six-hour window;
|
|
- precipitation timing based only on the near-term hourly slice;
|
|
- alert overlap inclusion/exclusion by near-term period;
|
|
- SPC outlook inclusion/exclusion by near-term period;
|
|
- SPC discussion records retained only for retained overlapping SPC days;
|
|
- no daily/daypart facts required.
|
|
- Add a regression test that an unsupported future report still returns an
|
|
actionable derivation error.
|
|
|
|
Validation:
|
|
|
|
```bash
|
|
go test ./internal/facts ./internal/forecast ./internal/timeutil
|
|
```
|
|
|
|
This stage is small enough for one implementation prompt.
|
|
|
|
## Stage 4: App Report Mapping And CLI Command
|
|
|
|
Goal: add explicit `generate near-term` support while preserving existing CLI
|
|
syntax and app behavior.
|
|
|
|
Files to inspect:
|
|
|
|
- `internal/app/app.go`
|
|
- `internal/app/app_test.go`
|
|
- `internal/cli/root.go`
|
|
- `internal/cli/root_test.go`
|
|
- `cmd/weatherreporter/main.go`
|
|
|
|
Implementation:
|
|
|
|
- Add app report kind:
|
|
|
|
```go
|
|
ReportNearTerm ReportKind = "near-term"
|
|
```
|
|
|
|
- Map `ReportNearTerm` to `report.NearTerm` in `reportIDForCommand`.
|
|
- Add `near-term` to CLI generate report parsing.
|
|
- Add help usage line:
|
|
|
|
```text
|
|
weatherreporter generate near-term [--config PATH] [--units VALUE] [--tz NAME] [--out PATH]
|
|
```
|
|
|
|
- Reuse existing generate command flags:
|
|
- allow `--config`;
|
|
- allow `--units`;
|
|
- allow `--tz`;
|
|
- allow `--out`;
|
|
- do not allow or require `--date`;
|
|
- do not allow or require storm `--start` / `--end`.
|
|
- Ensure the CLI returns an actionable error for unknown report names as today.
|
|
- Do not change batch commands.
|
|
|
|
Tests:
|
|
|
|
- Add CLI parser tests for:
|
|
- `generate near-term`;
|
|
- `generate near-term --config PATH`;
|
|
- `generate near-term --units us --tz America/Chicago --out PATH`;
|
|
- rejected `generate near-term --date YYYY-MM-DD`;
|
|
- rejected storm-only `--start` / `--end` on near-term if current parser
|
|
behavior supports this distinction.
|
|
- Add app resolution tests proving `ReportNearTerm` resolves `report.NearTerm`.
|
|
- Update help tests to assert `generate near-term` appears.
|
|
- Existing generate and run command tests must remain unchanged.
|
|
|
|
Validation:
|
|
|
|
```bash
|
|
go test ./internal/app ./internal/cli
|
|
go run ./cmd/weatherreporter --help
|
|
```
|
|
|
|
This stage is small enough for one implementation prompt.
|
|
|
|
## Stage 5: End-To-End Generation And Artifact Behavior
|
|
|
|
Goal: prove a near-term report can run through the app workflow and persist the
|
|
expected artifacts.
|
|
|
|
Files to inspect:
|
|
|
|
- `internal/app/app_test.go`
|
|
- `internal/state`
|
|
- `internal/promptinput`
|
|
- Weather API fixture server helpers in app tests
|
|
- distributor notification tests if report paths are asserted
|
|
|
|
Implementation:
|
|
|
|
- Add an app-level test that generates `ReportNearTerm` with fixture weather
|
|
data and fake Scriptorium.
|
|
- Assert:
|
|
- `ReportResult.Metadata.ReportID == report.NearTerm`;
|
|
- prompt ID is `weather.near_term_report`;
|
|
- managed report path uses artifact group `near-term`;
|
|
- data package path uses artifact group `near-term`;
|
|
- module snapshot contains the near-term module list in order;
|
|
- data package categories are unchanged;
|
|
- `hourly_forecast` contains only periods overlapping the six-hour window;
|
|
- `precip_timing` reflects only the six-hour window;
|
|
- `alert_digest` and SPC stanzas respect overlap behavior;
|
|
- AFD includes key messages and short term but not long term;
|
|
- `recent_changes.items` is empty when no rolling-window comparison exists.
|
|
- Add an app-level case for distributor notification only if existing tests
|
|
assert report-specific path rendering. The expected distributor templates
|
|
should work through existing `{artifact_group}`, `{report_id}`,
|
|
`{valid_start_date}`, and `{valid_start_time}` values without special
|
|
near-term behavior.
|
|
- Do not add `near_term` to scheduled batch tests.
|
|
|
|
Tests:
|
|
|
|
- Add stale-key checks if generated YAML is inspected:
|
|
- module intervals use `period_begins` / `period_ends`;
|
|
- top-level metadata keeps canonical `valid_period`.
|
|
- Ensure optional output copy via `--out` continues to use existing app copy
|
|
behavior for generated reports.
|
|
|
|
Validation:
|
|
|
|
```bash
|
|
go test ./internal/app ./internal/state ./internal/promptinput
|
|
```
|
|
|
|
This stage is small enough for one implementation prompt.
|
|
|
|
## Stage 6: Config Overrides And Examples
|
|
|
|
Goal: allow configured module overrides for `near_term` while keeping
|
|
maintained examples valid.
|
|
|
|
Files to inspect:
|
|
|
|
- `internal/config/reports.go`
|
|
- `internal/config/config_test.go`
|
|
- `docs/config.md` after implementation
|
|
- `examples/config.yml`
|
|
|
|
Implementation:
|
|
|
|
- Add report config key aliases:
|
|
- `near_term`
|
|
- `near-term`
|
|
- Map both aliases to `report.NearTerm`.
|
|
- Validate near-term module overrides through the existing module registry.
|
|
- Ensure incompatible modules fail clearly, for example
|
|
`derived_daily_summary` should not be compatible with `near_term`.
|
|
- Update config tests for:
|
|
- successful `reports.near_term.deterministic_modules`;
|
|
- successful `reports.near-term.deterministic_modules`;
|
|
- duplicate canonical near-term aliases rejected if both are present;
|
|
- incompatible daily-only module rejected.
|
|
- Update `examples/config.yml` only if it enumerates all report module
|
|
overrides. If it does not need a near-term override, do not add one just to
|
|
demonstrate the feature.
|
|
|
|
Validation:
|
|
|
|
```bash
|
|
go test ./internal/config ./internal/report ./internal/briefing
|
|
```
|
|
|
|
This stage is small enough for one implementation prompt.
|
|
|
|
## Stage 7: Implemented Documentation
|
|
|
|
Goal: update non-roadmap documentation after the feature exists.
|
|
|
|
Files to inspect and update:
|
|
|
|
- `docs/cli.md`
|
|
- `docs/config.md`
|
|
- `docs/operations.md`
|
|
- `docs/internal/report-registry.md`
|
|
- `docs/internal/module.md`
|
|
- `docs/internal/facts.md`
|
|
- `docs/internal/briefing.md`
|
|
- `docs/internal/prompt-input.md`
|
|
- `examples/config.yml`, only if changed in Stage 6
|
|
|
|
Documentation requirements:
|
|
|
|
- Describe `generate near-term` in CLI docs after implementation.
|
|
- Document that the first version is explicit generation only and is not part
|
|
of scheduled batches.
|
|
- Document the six-hour rolling valid period and that the duration is an
|
|
internal constant, not a config field.
|
|
- Document near-term report identity, artifact group, batch output name, prompt
|
|
ID, and module composition in internal docs.
|
|
- Document near-term config override keys only if Stage 6 implements them.
|
|
- Keep deferred items under roadmap docs only:
|
|
- configurable duration;
|
|
- batch membership;
|
|
- dedicated `derived_near_term_summary`;
|
|
- near-term Recent Changes comparison output.
|
|
|
|
Acceptance criteria:
|
|
|
|
- Non-roadmap docs describe only implemented behavior.
|
|
- Docs do not imply a duration config field or scheduled batch behavior.
|
|
- Maintained examples load.
|
|
|
|
Validation:
|
|
|
|
```bash
|
|
go test ./internal/config
|
|
git diff --check
|
|
```
|
|
|
|
This stage is small enough for one implementation prompt.
|
|
|
|
## Stage 8: Final Validation
|
|
|
|
Goal: run the complete project validation after implementation and docs are
|
|
updated.
|
|
|
|
Commands:
|
|
|
|
```bash
|
|
go test ./...
|
|
go run ./cmd/weatherreporter --help
|
|
git diff --check
|
|
```
|
|
|
|
Manual checks:
|
|
|
|
- `weatherreporter --help` lists `generate near-term`.
|
|
- No existing command syntax changed.
|
|
- `near_term` is absent from morning and evening batch membership.
|
|
- No non-roadmap docs describe unimplemented deferred near-term work.
|
|
- No config examples include secrets or invalid module IDs.
|
|
- Distributor bundle path rendering remains template-driven and does not need
|
|
report-specific branching.
|
|
|
|
This stage is small enough for one implementation prompt.
|
|
|
|
## Deferred Work
|
|
|
|
Do not include these in the first implementation:
|
|
|
|
- user-configurable near-term duration;
|
|
- scheduled near-term batch membership or a new high-frequency batch command;
|
|
- dedicated `derived_near_term_summary`;
|
|
- narrative forecast periods in the default near-term module list;
|
|
- separate AFD section modules;
|
|
- rolling-window Recent Changes comparison output;
|
|
- custom CLI duration flags;
|
|
- distributor-specific behavior for near-term reports.
|
|
|
|
## Open Questions
|
|
|
|
None block implementation.
|
|
|
|
Recommendation: keep the first version explicit and narrow: `generate
|
|
near-term`, six-hour constant, no batch membership, no Recent Changes output.
|
|
This fits the existing registry/module architecture and lets prompt quality be
|
|
tested before adding scheduler or comparison complexity.
|
|
|
|
Viable alternative: implement rolling-window Recent Changes immediately by
|
|
finding the most recent prior `near_term` report with an overlapping or adjacent
|
|
window. That could be useful later, but it needs a well-defined comparison
|
|
contract and should not block the first report implementation.
|