16 KiB
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_termand Go constantreport.NearTerm. - Add CLI command
weatherreporter generate near-term. - Do not add
--date,--start,--end, or duration flags for this report. - Do not add
near_termto morning or evening batches in the first implementation. - Define the valid-period duration with a package-owned constant, initially
6hours. - 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-termand batch output namenear-term.md. - Add comparison strategy constant
CompareRollingWindow = "rolling_window". - Declare
CompatiblePriorIDs: []report.ID{report.NearTerm}, but do not emit Recent Changes fornear_termin the first implementation. - Keep state prior lookup returning
nilfor rolling-window reports until a future comparison algorithm is designed. - Default module order is:
metadatacurrent_conditionshourly_forecastprecip_timingalert_digestspc_convective_outlooksarea_forecast_discussionspc_convective_discussionweather_story
- Configure the near-term
area_forecast_discussionmodule with onlykey_messagesandshort_termsections. - 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.gointernal/report/registry.gointernal/report/period.gointernal/report/daily_report.gointernal/report/period_test.gointernal/state/filesystem.go
Implementation:
-
Add
NearTerm ID = "near_term"ininternal/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:
const nearTermHours = 6 -
Add
nearTermDefinition()returning:ID: NearTermName: "Near-Term Report"PromptID: "weather.near_term_report"ComparisonStrategy: CompareRollingWindowArtifactGroup: "near-term"BatchOutputName: "near-term.md"Generated: trueCompatiblePriorIDs: []ID{NearTerm}Modules: nearTermModules()- no
MorningorEveningmembership resolve: resolveNearTerm
-
Implement
resolveNearTermas generation-time anchored:localNow := req.Now.In(req.Location) return timeutil.Period{ Start: localNow, End: localNow.Add(nearTermHours * time.Hour), }, nil -
Add
nearTermDefinition()toDefaultRegistry(). -
Add
NearTermtoRegistry.All()in a stable order afterDailyTomorrowand beforeThreeDay. -
Do not change
BatchReports. -
Leave
state.FindPriorSnapshotbehavior unchanged forCompareRollingWindow; it should returnnilbecause it only supports same-date and weekend lookup.
Tests:
- Add report period tests for:
- lookup succeeds for
NearTerm; Registry.All()includesNearTerm;- 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.
- lookup succeeds for
- 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.
- artifact group
Validation:
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.gointernal/briefing/modules.gointernal/module/module.gointernal/briefing/modules_test.gointernal/briefing/base_modules_test.gointernal/briefing/derived_modules_test.go
Implementation:
- Add
nearTermModules()ininternal/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.AreaForecastDiscussionwith options:module.AreaForecastDiscussionOptions{ Sections: []string{"key_messages", "short_term"}, } -
module.SPCConvectiveDiscussion -
module.WeatherStory
-
- Expand module
SupportedReportsininternal/briefing/modules.go:- include
report.NearTerminallReports; - include
report.NearTermforHourlyForecast; - do not include
report.NearTermforNarrativeForecast; - do not include
report.NearTermindaypartReports; - do not include
report.NearTermforDerivedDailySummary,DerivedDaypartSummaries,OutdoorWindows, orTomorrowPlanning.
- include
- Keep
PrecipTiming,AlertDigest,SPCConvectiveOutlooks,AreaForecastDiscussion,SPCConvectiveDiscussion, andWeatherStorycompatible throughallReports. - 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; HourlyForecastbuilds forreport.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:
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.gointernal/facts/facts_test.gointernal/forecastinternal/timeutilinternal/briefing/modules.go
Implementation:
- Add
report.NearTermhandling infacts.BuildDerived. - For near-term:
- populate
ValidPeriodHourlyPeriodsfrom the resolved six-hour valid period; - populate
ValidPeriodNarrativePeriodsif the existing generic selection already does so, but do not require it for default near-term modules; - build
PrecipTimingfromValidPeriodHourlyPeriods; - 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.
- populate
- 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:
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.gointernal/app/app_test.gointernal/cli/root.gointernal/cli/root_test.gocmd/weatherreporter/main.go
Implementation:
-
Add app report kind:
ReportNearTerm ReportKind = "near-term" -
Map
ReportNearTermtoreport.NearTerminreportIDForCommand. -
Add
near-termto CLI generate report parsing. -
Add help usage line:
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.
- allow
-
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/--endon near-term if current parser behavior supports this distinction.
- Add app resolution tests proving
ReportNearTermresolvesreport.NearTerm. - Update help tests to assert
generate near-termappears. - Existing generate and run command tests must remain unchanged.
Validation:
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.gointernal/stateinternal/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
ReportNearTermwith 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_forecastcontains only periods overlapping the six-hour window;precip_timingreflects only the six-hour window;alert_digestand SPC stanzas respect overlap behavior;- AFD includes key messages and short term but not long term;
recent_changes.itemsis 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_termto 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.
- module intervals use
- Ensure optional output copy via
--outcontinues to use existing app copy behavior for generated reports.
Validation:
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.gointernal/config/config_test.godocs/config.mdafter implementationexamples/config.yml
Implementation:
- Add report config key aliases:
near_termnear-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_summaryshould not be compatible withnear_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.
- successful
- Update
examples/config.ymlonly 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:
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.mddocs/config.mddocs/operations.mddocs/internal/report-registry.mddocs/internal/module.mddocs/internal/facts.mddocs/internal/briefing.mddocs/internal/prompt-input.mdexamples/config.yml, only if changed in Stage 6
Documentation requirements:
- Describe
generate near-termin 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:
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:
go test ./...
go run ./cmd/weatherreporter --help
git diff --check
Manual checks:
weatherreporter --helplistsgenerate near-term.- No existing command syntax changed.
near_termis 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.