Files
weatherreporter/docs/roadmap/implementation.md

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_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:

    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:

    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:

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:

      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:

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:

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:

    ReportNearTerm ReportKind = "near-term"
    
  • Map ReportNearTerm to report.NearTerm in reportIDForCommand.

  • Add near-term to 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.
  • 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:

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:

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:

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:

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 --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.