Finalized the initial development roadmap

This commit is contained in:
2026-05-29 11:41:50 -05:00
parent 577b42e243
commit 05b56d6ea6
2 changed files with 413 additions and 237 deletions

View File

@@ -7,12 +7,26 @@ The goal is to build the application in stable layers. Each stage should leave t
## Guiding Implementation Principles
- Build deterministic data preparation before LLM rendering.
- Keep CLI, adapters, domain logic, state, and prompt-variable construction separate.
- Keep CLI, adapters, domain logic, state, and prompt input construction separate.
- Use fixture-driven tests for forecast processing and briefing builders.
- Persist intermediate artifacts so failed or low-quality reports can be inspected.
- Add one report type fully before generalizing to all report types.
- Treat `scriptorium` as an external adapter during the prototype.
- Do not build the storm-monitoring agent until scheduled report generation is reliable.
- Do not support multiple weatherreporter locations in the MVP; use one configured Weather API endpoint.
## MVP Decisions Locked
- Use one configured Weather API endpoint; do not expose MVP location selection.
- Use the Go standard library for CLI parsing.
- Use `gopkg.in/yaml.v3` for YAML configuration.
- Default Weather API query values are `format=json`, `units=us`, and `tz=Chicago`.
- Default missing-source policy is `warn`.
- Fetch full `/forecast/hourly` and `/forecast/narrative` products; Go owns report-period selection.
- Require hourly forecast data for normal scheduled reports.
- Use `scriptorium render` as an always-on preflight before `scriptorium run` for generated reports.
- Pass prompt input to `scriptorium` with `--input data_package=<path>`.
- Identify source payloads with SHA-256 over canonical/minified raw `data` JSON.
## Stage 0: Repository Skeleton and Architecture Baseline
@@ -35,7 +49,7 @@ Create the project skeleton, commit the architecture documents, and establish th
4. Add this implementation roadmap.
5. Create minimal package directories and placeholder files where useful.
6. Add basic build/test tooling.
7. Add a minimal `weatherreporter --help` command.
7. Add a minimal `weatherreporter --help` command using the Go standard library.
### Deliverables
@@ -66,20 +80,24 @@ Implement configuration loading and a stable command shape before integrating ex
### Work Items
1. Define configuration structs for:
- Weather API settings.
- Locations.
- Location time zones.
- Weather API base URL, timeout, precision, units, and timezone.
- Missing-source behavior, with a global default and optional per-source overrides.
- `scriptorium` settings.
- Workspace paths.
- Report output paths.
- Daypart definitions.
- Recent-change thresholds.
2. Implement built-in defaults in `internal/config/defaults.go`.
2. Implement built-in defaults in `internal/config/defaults.go`:
- `units=us`
- `tz=Chicago`
- `format=json`
- missing-source policy `warn`
3. Implement YAML config loading from:
- `/usr/local/etc/weatherreporter/config.yml`
- CLI override via `--config`
4. Implement config validation.
5. Implement basic command structure:
4. Use `gopkg.in/yaml.v3` for YAML parsing.
5. Implement config validation.
6. Implement basic command structure with the Go standard library:
- `generate daily`
- `generate tomorrow`
- `generate three-day`
@@ -87,27 +105,35 @@ Implement configuration loading and a stable command shape before integrating ex
- `generate storm`
- `run morning`
- `run evening`
6. Commands may initially return “not implemented” after config and request resolution.
7. Add time-zone and clock helpers.
7. Add CLI flag parsing for:
- `--config`
- `--units`
- `--tz`
- `--out`
- optional `--date` for Daily Today, accepting `YYYY-MM-DD` and defaulting to the current local date in the configured timezone
- `--start` and `--end` for manual Storm Reports
8. Commands may initially return "not implemented" after config and request resolution.
9. Add time-zone and clock helpers.
### Deliverables
- Config can be loaded, validated, and inspected in tests.
- CLI commands parse expected flags.
- CLI commands parse expected flags without a CLI framework dependency.
- App-layer request structs exist for report generation and scheduled batches.
### Tests
- Config defaults load successfully.
- Config defaults load successfully, including `units=us`, `tz=Chicago`, and missing-source policy `warn`.
- Example config file load test.
- Invalid config produces actionable errors.
- CLI parser tests for major commands.
- CLI parser tests for major commands and shared flags.
- Storm `--start`/`--end` parsing tests.
- Time-zone resolution tests.
### Done Criteria
- CLI request handling is stable enough that later stages can attach real behavior without reshaping commands.
- Configuration can represent at least one location and the default daypart set.
- Configuration can represent the single Weather API endpoint, default units/timezone, default daypart set, and missing-source policy.
## Stage 2: Weather API Adapter and Forecast Bundle
@@ -117,8 +143,8 @@ Fetch normalized weather data from the internal weather API and represent it as
### Key References
- `docs/integrations/weatherapi.md` describes the weatherapi public API
- The local API endpoint is available at `https://weather.api.rakestrawhome.com/` and will return live data
- `docs/integrations/weatherapi.md` describes the weatherapi public API.
- The local API endpoint is available at `https://weather.api.rakestrawhome.com/` and will return live data.
### Packages Introduced or Expanded
@@ -130,30 +156,57 @@ Fetch normalized weather data from the internal weather API and represent it as
1. Define the internal `forecast.Bundle` type.
2. Define source substructures for:
- Latest observation.
- Current conditions.
- Hourly forecast data.
- Daily forecast data (NOTE: not yet implemented upstream in weatherapi, so this can remain a stub in the initial implementation).
- NWS narrative forecast periods.
- NWS alerts.
- NWS forecast discussion.
- NWS weather story (NOTE: not yet implemented upstream in weatherapi, so this can remain a stub in the initial implementation).
3. Implement the weather API client.
4. Add context-aware HTTP calls and timeouts.
5. Add actionable errors for failed API calls and decode failures.
6. Add fixture support for tests.
7. Optionally add a debug command or app method to fetch and save the raw normalized bundle.
- Daily forecast data as a stub source slot until upstream support exists.
- NWS weather story as a stub source slot until upstream support exists.
3. Implement the weather API client as a fan-out adapter that assembles one bundle from multiple endpoints.
4. Fetch full `/forecast/hourly` and `/forecast/narrative` products, not day-slice endpoints, so Go domain code owns report-period selection.
5. Apply configured query defaults to requests:
- `format=json`
- `units=us`, unless overridden
- `tz=Chicago`, unless overridden on endpoints that support timezone
6. Add context-aware HTTP calls and timeouts.
7. Add source provenance to the bundle:
- endpoint
- query
- fetched time
- issued/updated time when available
- SHA-256 over canonical/minified raw `data` JSON
- warnings
8. Represent source warnings as first-class records with source name, code, severity, message, endpoint, and completeness impact.
9. Require hourly forecast data for normal scheduled reports.
10. Apply configured missing-source policy to missing observations, current conditions, alerts, discussion, daily forecast stub, weather story stub, and malformed non-required source sections:
- `error`: fail the bundle fetch
- `warn`: include a source warning and continue
- `none`: omit the warning and continue
11. Add actionable errors for failed API calls and decode failures.
12. Add fixture support for tests.
13. Add a debug command or app method to fetch and save the raw normalized bundle for fixture capture and inspection.
### Deliverables
- Weather API adapter can fetch a bundle for a configured location.
- Weather API adapter can fetch and assemble a bundle from the configured endpoint.
- Forecast bundle type is available to downstream packages.
- Bundle source provenance and warnings are inspectable.
- Tests can use fixtures without real API calls.
### Tests
- Decode representative API fixture into `forecast.Bundle`.
- Decode representative API fixtures into `forecast.Bundle`.
- Fan-out success across source endpoints.
- HTTP error handling.
- Timeout/cancellation behavior.
- `data:null` behavior under `error`, `warn`, and `none`.
- Missing or malformed source sections.
- Query construction for `units=us` and `tz=Chicago`.
- Full-product forecast endpoint selection.
- Required hourly forecast behavior.
- SHA-256 source identity behavior.
### Done Criteria
@@ -211,7 +264,7 @@ Implement deterministic forecast processing needed by the Daily Report.
### Goal
Centralize report definitions and valid-period behavior before building report-specific briefings.
Centralize report definitions, compatible comparison strategies, and valid-period behavior before building report-specific briefings.
### Packages Introduced or Expanded
@@ -230,19 +283,24 @@ Centralize report definitions and valid-period behavior before building report-s
2. Define report metadata structures.
3. Define a report `Definition` contract.
4. Implement a registry.
5. Implement valid-period resolvers:
- Today Daily Report.
- Tomorrow Planning Brief.
- 3-Day Outlook.
- Weekend Outlook.
- Storm Report placeholder.
6. Define default prompt IDs:
5. Implement valid-period resolvers using the configured local timezone, default `Chicago`, and half-open `[start,end)` intervals:
- Today Daily Report: current local civil day, `[00:00, next 00:00)`.
- Tomorrow Planning Brief: next local civil day.
- 3-Day Outlook: generation time through local midnight after the second following local civil day.
- Weekend Outlook: Monday through Thursday covers Saturday 00:00 to Monday 00:00; Friday and Saturday cover `max(generation time, Friday 18:00)` to Monday 00:00; scheduled Sunday morning skips Weekend Outlook.
- Storm Report: explicit `--start` and `--end`.
6. Parse manual storm period bounds from `YYYY-MM-DDTHH:MM` in the configured timezone or RFC3339 timestamps with explicit offsets.
7. Define default prompt IDs:
- `weather.daily_report`
- `weather.tomorrow_report`, or reuse `weather.daily_report` if preferred.
- `weather.daily_report` for `daily_tomorrow`; this prompt covers one civil day.
- `weather.three_day_outlook`
- `weather.weekend_outlook`
- `weather.storm_report`
7. Implement batch membership rules:
8. Define Recent Changes matching strategies in report definitions:
- Daily Today, Daily Tomorrow, and compatible date slices from multi-day reports may compare by same valid local date when marked compatible.
- Weekend compares by same weekend window.
- Storm compares by explicit event window.
9. Implement batch membership rules:
- Morning batch: Daily Today, 3-Day Outlook, Weekend Outlook except Sunday.
- Evening batch: Daily Tomorrow.
@@ -250,20 +308,21 @@ Centralize report definitions and valid-period behavior before building report-s
- App layer can resolve which reports should run for a command.
- Each report has a valid period independent of generation time.
- Report definitions map to prompt IDs.
- Report definitions map to prompt IDs and comparison strategies.
### Tests
- Daily valid period for different generation times.
- Tomorrow valid period from evening generation.
- 3-day period calculation.
- 3-Day period calculation from generation time.
- Weekend period calculation on Monday, Friday, Saturday, and Sunday.
- Storm manual period parsing and validation.
- Morning batch skips Weekend Outlook on Sunday.
- Registry lookup errors are actionable.
### Done Criteria
- Report identity and period behavior are stable.
- Report identity, period behavior, and compatible comparison rules are stable.
- Later stages can add builders without changing CLI semantics.
## Stage 5: Daily Briefing Builder
@@ -282,12 +341,15 @@ Build the first complete report-specific briefing package without invoking the L
### Work Items
1. Define common briefing metadata:
- Schema version.
- RunID.
- Report type.
- Variant.
- Location.
- Generation time.
- Configured units and timezone.
- Valid start/end.
- Source timestamps or hashes.
- Source location ID/name when provided by upstream.
- Source timestamps, SHA-256 hashes, and source warnings.
2. Define the Daily Report briefing schema.
3. Build Daily Report briefing content:
- Bottom-line inputs.
@@ -296,7 +358,7 @@ Build the first complete report-specific briefing package without invoking the L
- Best/worst outdoor window inputs, if derivable.
- NWS narrative periods relevant to the day.
- Forecast discussion summary or selected text from the API data.
- Weather story summary or selected text from the API data.
- Weather story summary or selected text when upstream support exists.
4. Add JSON output for the briefing package.
5. Add an app workflow that can generate the Daily briefing and write it to disk for inspection.
@@ -310,6 +372,8 @@ Build the first complete report-specific briefing package without invoking the L
- Daily briefing from representative fixture.
- Alerts included/excluded correctly.
- Source context selection.
- Source warnings included correctly.
- RunID included correctly.
- Empty or quiet-weather behavior.
- Snapshot metadata completeness.
@@ -318,97 +382,69 @@ Build the first complete report-specific briefing package without invoking the L
- The Daily briefing package is useful as prompt input.
- The app can produce the briefing artifact from real or fixture data.
## Stage 6: Prompt Variable Builder
## Stage 6: Prompt Input Package and Scriptorium Render Preflight
### Goal
Convert a briefing package into the structured variable payload expected by `scriptorium` prompts.
### Packages Introduced or Expanded
- `internal/promptvars`
- `internal/briefing`
- `internal/report`
- `internal/app`
### Work Items
1. Define prompt variable schema structures.
2. Build variables from report metadata and briefing content.
3. Include placeholders for Recent Changes, initially empty.
4. Validate required fields before rendering.
5. Write vars JSON to the workspace.
6. Ensure vars output is stable and inspectable.
### Deliverables
- Daily Report prompt vars can be generated and written to a file.
- The vars file is suitable for `scriptorium run --vars-file`.
### Tests
- Prompt vars generated from Daily briefing fixture.
- Missing required fields fail validation.
- JSON output is deterministic where practical.
### Done Criteria
- The app can prepare a complete vars file for a Daily Report.
- LLM rendering is the only missing step for the first end-to-end report.
## Stage 7: Scriptorium Adapter and First End-to-End Daily Report
### Goal
Invoke `scriptorium` as a subprocess and produce the first rendered Markdown report.
Convert a briefing package into the structured `data_package` input expected by `scriptorium` prompts and validate prompt wiring without LLM generation.
### Key References
- `docs/integrations/scriptorium.md` describes the CLI contract for running `scriptorium` as a subprocess.
- `docs/integrations/scriptorium.md` describes the CLI contract for `scriptorium render`.
### Packages Introduced or Expanded
- `internal/promptinput`
- `internal/briefing`
- `internal/report`
- `internal/adapters/scriptorium`
- `internal/app`
- `internal/state`, minimally if needed for output paths
### Work Items
1. Define `scriptorium.Runner` interface and request/result types.
2. Implement subprocess execution with `exec.CommandContext`.
3. Pass arguments without shell interpolation.
4. Prefer `--vars-file` for prompt variables.
5. Capture stderr and stdout with reasonable limits.
6. Apply timeout and cancellation.
7. Return actionable errors for nonzero exits.
8. Wire Daily Report generation end-to-end:
- Fetch bundle.
- Build briefing.
- Build vars.
- Run `scriptorium`.
- Write Markdown report.
1. Define prompt input data package schema structures.
2. Build `data_package` JSON from report metadata, briefing content, source warnings, RunID, and an initially empty Recent Changes section.
3. Validate required data package fields before rendering.
4. Write data package JSON to the workspace.
5. Implement `scriptorium render` support in the adapter.
6. Invoke preflight as:
```text
scriptorium render \
--prompt <prompt_id> \
--input data_package=<path> \
--format json
```
7. Capture stdout and stderr separately.
8. Persist render/preflight output for inspection.
9. Treat render preflight as always-on before `scriptorium run` for MVP generated reports.
### Deliverables
- `weatherreporter generate daily --location home --out ./daily.md` produces a Markdown report.
- Failures include useful context.
- Daily Report data package can be generated and written to a file.
- The data package is suitable for `scriptorium render --input data_package=<path>`.
- Prompt/input wiring can be checked without LLM execution.
### Tests
- Adapter command construction using a fake command runner or fake executable.
- Nonzero exit handling.
- Timeout behavior.
- App workflow test using fake weather client and fake `scriptorium` runner.
- Data package generated from Daily briefing fixture.
- Missing required fields fail validation.
- JSON output is deterministic where practical.
- Adapter command construction for `scriptorium render`.
- Nonzero render exit handling.
- Always-on preflight behavior in the generation workflow.
### Done Criteria
- The first report can be generated end-to-end.
- `scriptorium` is isolated behind the adapter package.
- The app can prepare and preflight a complete data package for a Daily Report.
- LLM rendering is the only missing step for the first end-to-end report.
## Stage 8: Filesystem State Store and Metadata Persistence
## Stage 7: Filesystem State Store and Metadata Baseline
### Goal
Persist report artifacts and metadata in a durable, inspectable structure.
Persist report artifacts and metadata in a durable, inspectable structure before the first LLM-generated report.
### Packages Introduced or Expanded
@@ -420,15 +456,19 @@ Persist report artifacts and metadata in a durable, inspectable structure.
1. Define state store interface.
2. Implement filesystem-backed store.
3. Persist briefing snapshots.
4. Persist prompt variable files.
5. Persist report metadata.
6. Persist rendered Markdown reports when output path is managed by the app.
7. Use atomic writes where practical.
8. Implement lookup for prior comparable snapshots.
4. Persist prompt input data package files.
5. Persist `scriptorium render` preflight output.
6. Persist report metadata.
7. Add RunID as an explicit metadata concept based on generation timestamp plus report ID.
8. Name managed report files with the generation timestamp to avoid overwriting previous runs for the same valid period.
9. Link valid period, RunID, briefing snapshot, data package, preflight output, rendered report, source warnings, and source hashes in metadata.
10. Use atomic writes where practical.
11. Implement lookup for prior comparable Daily snapshots.
12. Keep paths narrow and predictable.
### Deliverables
- Each generated report has associated metadata and briefing snapshot.
- Each Daily preflight run has associated metadata, RunID, briefing snapshot, data package, and render output.
- Prior comparable snapshot lookup works for Daily Reports.
### Tests
@@ -436,25 +476,92 @@ Persist report artifacts and metadata in a durable, inspectable structure.
- Atomic write behavior where feasible.
- Metadata round-trip.
- Snapshot path generation.
- Data package path generation.
- Preflight output path generation.
- Timestamped managed report path generation.
- RunID metadata behavior.
- Prior snapshot lookup.
- Narrow-path safety behavior.
### Done Criteria
- Daily reports leave enough state for inspection and future Recent Changes.
- Daily report preparation leaves enough state for inspection and future Recent Changes.
- State layout is predictable and documented.
## Stage 8: Scriptorium Run Adapter and First End-to-End Daily Report
### Goal
Invoke `scriptorium run` as a subprocess and produce the first rendered Markdown report.
### Key References
- `docs/integrations/scriptorium.md` describes the CLI contract for running `scriptorium` as a subprocess.
### Packages Introduced or Expanded
- `internal/adapters/scriptorium`
- `internal/app`
- `internal/state`
### Work Items
1. Define `scriptorium.Run` request/result types or extend the runner interface introduced for render preflight.
2. Implement subprocess execution with `exec.CommandContext`.
3. Pass arguments without shell interpolation.
4. Pass the prompt input data package with `--input data_package=<path>`.
5. Invoke generation as:
```text
scriptorium run \
--prompt <prompt_id> \
--input data_package=<path> \
--out <artifact_path>
```
6. Capture stderr and stdout with reasonable limits.
7. Apply timeout and cancellation.
8. Return actionable errors for nonzero exits, including exit code `2`, which can still produce output.
9. Wire Daily Report generation end-to-end:
- Fetch bundle.
- Build briefing.
- Build data package.
- Run render preflight.
- Run `scriptorium`.
- Write Markdown report.
- Persist metadata and snapshots.
### Deliverables
- `weatherreporter generate daily --out ./daily.md` produces a Markdown report.
- Failures include useful context.
- The first end-to-end report already has durable briefing, data package, metadata, and source provenance.
### Tests
- Adapter command construction using a fake command runner or fake executable.
- Nonzero exit handling.
- Exit code `2` handling.
- Timeout behavior.
- Always-on preflight before run.
- App workflow test using fake weather client and fake `scriptorium` runner.
### Done Criteria
- The first report can be generated end-to-end.
- `scriptorium` is isolated behind the adapter package.
## Stage 9: Recent Changes for Daily Reports
### Goal
Add structured comparison of Daily Report briefing snapshots and include meaningful changes in prompt variables.
Add structured comparison of Daily Report briefing snapshots and include meaningful changes in prompt input data packages.
### Packages Introduced or Expanded
- `internal/changes`
- `internal/state`
- `internal/promptvars`
- `internal/promptinput`
- `internal/app`
### Work Items
@@ -470,12 +577,12 @@ Add structured comparison of Daily Report briefing snapshots and include meaning
- Alert changes.
- Wind gust changes.
- Snow/ice/thunder risk changes.
6. Add Recent Changes to prompt vars.
6. Add Recent Changes to the data package.
7. Omit or minimize Recent Changes when no meaningful changes exist.
### Deliverables
- Daily Report vars include Recent Changes when appropriate.
- Daily Report data packages include Recent Changes when appropriate.
- Daily Report generation persists current snapshot after comparison.
### Tests
@@ -485,11 +592,11 @@ Add structured comparison of Daily Report briefing snapshots and include meaning
- Temperature threshold crossing.
- Precipitation timing shift.
- Alert added/removed behavior.
- Comparison uses valid period, not just generation time.
- Comparison uses valid period and compatible strategy, not just generation time.
### Done Criteria
- The Daily Report can say what changed relative to the prior report covering the same forecast period.
- The Daily Report can say what changed relative to a prior compatible report covering the same forecast period.
- Markdown report text is not used as the comparison source.
## Stage 10: Tomorrow Planning Brief
@@ -508,24 +615,24 @@ Add the evening Tomorrow Planning Brief using the Daily Report machinery where p
### Work Items
1. Implement the `daily_tomorrow` report definition fully.
2. Reuse or specialize the Daily briefing builder for tomorrows valid date.
2. Reuse or specialize the Daily briefing builder for tomorrow's valid date.
3. Add any tomorrow-specific planning fields, such as:
- Morning readiness note inputs.
- Commute/school/workday concerns.
- What may change overnight.
4. Ensure comparison can find a prior report covering the same valid day where appropriate.
4. Ensure comparison can find a prior compatible report covering the same valid local date.
5. Implement `run evening` as Daily Tomorrow.
### Deliverables
- `weatherreporter generate tomorrow --location home` works end-to-end.
- `weatherreporter run evening --location home` works.
- `weatherreporter generate tomorrow` works end-to-end.
- `weatherreporter run evening` works.
### Tests
- Tomorrow valid-period calculation.
- Tomorrow briefing uses the correct date.
- Recent Changes can compare against prior 3-Day or prior Tomorrow snapshot if configured.
- Recent Changes can compare against a compatible prior Tomorrow, Daily, or 3-Day snapshot when configured by the registry.
- Evening batch includes only the expected report.
### Done Criteria
@@ -551,32 +658,32 @@ Add the 3-Day Outlook report using the same architecture.
1. Implement 3-Day valid-period resolution.
2. Build a 3-Day briefing package.
3. Summarize each day:
3. Summarize each day or partial day:
- Overall character.
- Temperature range.
- Precipitation/storm/winter/heat/wind risks.
- Best/worst windows if derivable.
- Relevant alerts.
4. Attach broader NWS context, especially forecast discussion and weather story inputs.
4. Attach broader NWS context, especially forecast discussion and weather story inputs when available.
5. Implement 3-Day Recent Changes strategy.
6. Add end-to-end generation.
### Deliverables
- `weatherreporter generate three-day --location home` produces Markdown.
- `weatherreporter generate three-day` produces Markdown.
- Morning batch can include the 3-Day Outlook.
### Tests
- Three-day valid period.
- Daily aggregation across three days.
- Three-day valid period from generation time.
- Daily aggregation across the 3-Day window.
- Alert overlap across multi-day period.
- Recent Changes across multi-day snapshots.
- Quiet-weather behavior.
### Done Criteria
- The 3-Day Outlook is generated using the same registry, briefing, vars, state, and rendering pipeline as the Daily Report.
- The 3-Day Outlook is generated using the same registry, briefing, data package, state, and rendering pipeline as the Daily Report.
## Stage 12: Weekend Outlook
@@ -595,9 +702,9 @@ Add the Weekend Outlook with day-of-week-sensitive period behavior.
### Work Items
1. Implement Weekend valid-period resolution:
- Monday through Thursday: upcoming Saturday/Sunday, optionally Friday evening if configured.
- Friday: Friday evening through Sunday night.
- Saturday: remaining weekend.
- Monday through Thursday: upcoming Saturday 00:00 through Monday 00:00.
- Friday: `max(generation time, Friday 18:00)` through Monday 00:00.
- Saturday: generation time through Monday 00:00.
- Sunday: normally not generated by the scheduled morning batch.
2. Build Weekend briefing package.
3. Emphasize planning fields:
@@ -611,8 +718,8 @@ Add the Weekend Outlook with day-of-week-sensitive period behavior.
### Deliverables
- `weatherreporter generate weekend --location home` produces Markdown.
- `weatherreporter run morning --location home` includes Weekend Outlook except Sunday.
- `weatherreporter generate weekend` produces Markdown.
- `weatherreporter run morning` includes Weekend Outlook except Sunday.
### Tests
@@ -643,27 +750,27 @@ Make scheduled workflows reliable enough for unattended execution by cron, syste
1. Finalize `run morning` workflow.
2. Finalize `run evening` workflow.
3. Decide failure behavior:
- Continue remaining reports after one report fails, or fail fast.
- Return aggregate status.
4. Add structured run summaries.
5. Ensure each report run records enough metadata for troubleshooting.
6. Add CLI flags for output directory, location, and optional dry-run/vars-only mode if desired.
7. Add logging suitable for scheduled execution.
3. Continue remaining independent reports after one report fails.
4. Return nonzero from the CLI if any report failed.
5. Add structured aggregate run summaries.
6. Ensure each report run records enough metadata for troubleshooting.
7. Add CLI flags for output directory and optional dry-run/data-package-only mode if desired.
8. Add logging suitable for scheduled execution.
### Deliverables
- Morning batch can generate Daily, 3-Day, and Weekend reports.
- Evening batch can generate Tomorrow Planning Brief.
- Failures are understandable from logs and metadata.
- Failures are understandable from logs, metadata, and aggregate summaries.
### Tests
- Morning batch report selection.
- Evening batch report selection.
- Partial failure behavior.
- Partial failure continues independent reports.
- Aggregate nonzero exit behavior.
- Output path behavior.
- Dry-run or vars-only behavior, if implemented.
- Dry-run or data-package-only behavior, if implemented.
### Done Criteria
@@ -686,11 +793,11 @@ Add manual Storm Report generation without building the automatic monitoring age
### Work Items
1. Implement Storm Report definition.
2. Define storm valid-period behavior.
2. Require explicit storm valid-period bounds via `--start` and `--end`.
3. Build storm briefing package from:
- Active alerts.
- Forecast discussion.
- Weather story.
- Weather story when available.
- Relevant hourly/daily periods.
- NWS narrative periods.
4. Include storm-specific fields:
@@ -702,7 +809,7 @@ Add manual Storm Report generation without building the automatic monitoring age
- Confidence and uncertainty inputs.
- What to watch next.
5. Add manual command:
- `weatherreporter generate storm --location home`
- `weatherreporter generate storm --start <time> --end <time>`
### Deliverables
@@ -714,6 +821,7 @@ Add manual Storm Report generation without building the automatic monitoring age
- Storm briefing with active alerts.
- Storm briefing with forecast discussion but no active alert.
- Quiet/no-storm behavior.
- Manual period parsing and validation.
- Relevant source selection.
### Done Criteria
@@ -740,7 +848,8 @@ Make generated artifacts easy to inspect and debug.
- Show metadata for a report.
- Show prior comparable snapshot chosen for Recent Changes.
- Emit briefing JSON without rendering.
- Emit prompt vars without rendering.
- Emit data package JSON without rendering.
- Show source warnings and provenance.
2. Add clear paths to generated artifacts in command output.
3. Ensure logs do not dump large weather payloads by default.
@@ -748,12 +857,14 @@ Make generated artifacts easy to inspect and debug.
- Developers can inspect why a report was generated a certain way.
- Recent Changes comparison inputs are discoverable.
- Source warnings are discoverable.
### Tests
- Inspection command behavior with fixture state.
- Missing artifact errors.
- Metadata lookup behavior.
- Source warning display behavior.
### Done Criteria
@@ -781,7 +892,7 @@ Potentially:
3. Use source signals such as:
- Active alerts.
- Forecast discussion hazard wording.
- Weather Story emphasis.
- Weather Story emphasis when available.
- Hourly/daily threshold crossings.
- Material forecast changes toward higher impact.
4. Add an LLM event evaluator through `scriptorium` or a future native LLM adapter.
@@ -797,7 +908,7 @@ Potentially:
### Deliverables
- `weatherreporter evaluate storm --location home` can decide whether a Storm Report is warranted.
- `weatherreporter evaluate storm` can decide whether a Storm Report is warranted.
- Event lifecycle state is persisted.
- Storm Report updates are generated only for meaningful changes.
@@ -819,28 +930,29 @@ Potentially:
The first meaningful milestone should be:
```text
weatherreporter generate daily --location home --out ./daily.md
weatherreporter generate daily --out ./daily.md
```
This command should:
1. Load config.
2. Fetch weather data.
2. Fetch weather data from the configured endpoint.
3. Build a Daily briefing package.
4. Build prompt variables.
5. Invoke `scriptorium`.
6. Write Markdown output.
7. Persist metadata and snapshots.
4. Build a prompt input data package.
5. Run `scriptorium render` preflight.
6. Invoke `scriptorium run`.
7. Write Markdown output.
8. Persist metadata, source provenance, source warnings, the briefing snapshot, and the data package.
Do not implement all report types before this milestone. One complete vertical slice will reveal schema, state, prompt-variable, and adapter issues earlier than a broad but shallow implementation.
Do not implement all report types before this milestone. One complete vertical slice will reveal schema, state, prompt input, and adapter issues earlier than a broad but shallow implementation.
## Suggested Second Implementation Milestone
The second milestone should be:
```text
weatherreporter run morning --location home
weatherreporter run evening --location home
weatherreporter run morning
weatherreporter run evening
```
At this point, the app should support:
@@ -852,13 +964,14 @@ At this point, the app should support:
- Recent Changes for all scheduled report types.
- Filesystem state and metadata.
- Reliable scheduled execution.
- Partial-failure continuation with nonzero aggregate exit status.
## Suggested Third Implementation Milestone
The third milestone should be:
```text
weatherreporter generate storm --location home
weatherreporter generate storm --start 2026-05-29T18:00 --end 2026-05-30T06:00
```
At this point, Storm Reports can be generated manually using the same pipeline. Automatic storm monitoring should remain future work until manual Storm Reports are useful and stable.
@@ -871,6 +984,7 @@ Do not implement these in the initial prototype unless required by real use:
- Daemon mode.
- Automatic storm-monitoring agent.
- Database-backed state.
- Multi-location weatherreporter selection.
- Multi-user authorization.
- Public HTTP API.
- Complex plugin system.
@@ -882,7 +996,7 @@ Do not implement these in the initial prototype unless required by real use:
The most important early design decision is to make the briefing package the central artifact. Once the briefing package is stable, every report follows the same basic path:
```text
report definition -> valid period -> forecast selection -> briefing package -> Recent Changes -> prompt vars -> scriptorium -> report metadata
report definition -> valid period -> forecast selection -> briefing package -> Recent Changes -> data package -> scriptorium -> report metadata
```
This keeps the application modular, testable, and easy to extend with future report types.