Document internal component boundaries
This commit is contained in:
89
docs/internal/app-orchestration.md
Normal file
89
docs/internal/app-orchestration.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# App Orchestration Internals
|
||||
|
||||
This document describes the implemented workflow coordinator in `internal/app`.
|
||||
|
||||
## Purpose
|
||||
|
||||
`internal/app` coordinates top-level use cases: generating one report, running
|
||||
morning or evening batches, building inspectable briefing artifacts, fetching
|
||||
weather bundles, and reading existing artifacts for inspection.
|
||||
|
||||
## Inputs And Outputs
|
||||
|
||||
Inputs:
|
||||
|
||||
- app request structs containing config, report or batch selection, clock time,
|
||||
optional report date, optional Storm Report bounds, output paths, renderer
|
||||
fakes, or state-store fakes
|
||||
- resolved report definitions from `internal/report`
|
||||
- forecast bundles from the Weather API adapter
|
||||
- prior briefing snapshots from `internal/state`
|
||||
|
||||
Outputs:
|
||||
|
||||
- report results with briefing, data package, preflight, report, metadata,
|
||||
prior snapshot, Recent Changes, and Scriptorium results
|
||||
- batch summaries with per-report status and artifact paths
|
||||
- inspection JSON values for reports, metadata, briefings, data packages, prior
|
||||
snapshots, and source provenance
|
||||
|
||||
## Boundaries
|
||||
|
||||
- The package coordinates workflow order.
|
||||
- It does not parse CLI flags, load YAML files directly, implement HTTP calls,
|
||||
derive forecast facts, define report periods, compare Markdown, or construct
|
||||
Scriptorium argv.
|
||||
|
||||
## Config Fields Used
|
||||
|
||||
- `weather_api.*` for Weather API client construction and briefing metadata
|
||||
- `scriptorium.*` for renderer construction
|
||||
- `workspace.*` for filesystem state
|
||||
- `dayparts` for daily and outlook summarization
|
||||
- `recent_change.*` for structured Recent Changes thresholds
|
||||
|
||||
## External Adapters Used
|
||||
|
||||
- `internal/adapters/weatherapi` for forecast bundle fetching
|
||||
- `internal/adapters/scriptorium` for render preflight and report generation
|
||||
- `internal/state` filesystem store for persisted artifacts
|
||||
|
||||
## State Or Manifest Behavior
|
||||
|
||||
Generation saves the briefing snapshot, data package, preflight result when
|
||||
available, rendered report, and metadata. Metadata links all managed artifact
|
||||
paths. Inspection workflows read existing state and do not fetch weather data or
|
||||
invoke Scriptorium.
|
||||
|
||||
## Skip And Resume Behavior
|
||||
|
||||
There is no resume workflow. Batch generation continues remaining independent
|
||||
reports after one report fails, then reports aggregate success and failure
|
||||
counts.
|
||||
|
||||
## Failure Behavior
|
||||
|
||||
- Resolve errors stop the requested workflow before fetching weather data.
|
||||
- Weather API or briefing errors stop that report before Scriptorium is called.
|
||||
- Render preflight runs before Scriptorium report generation.
|
||||
- If render preflight returns a result and an error, preflight JSON and metadata
|
||||
are persisted before the error is returned.
|
||||
- If Scriptorium report generation returns an error after writing output,
|
||||
metadata and the managed report path remain inspectable.
|
||||
- Batch failures are recorded per report and surfaced through aggregate batch
|
||||
failure.
|
||||
|
||||
## Tests
|
||||
|
||||
Inspect:
|
||||
|
||||
- `internal/app/app_test.go`
|
||||
- `internal/cli/root_test.go`
|
||||
- `internal/state/filesystem_test.go`
|
||||
|
||||
## Invariants
|
||||
|
||||
- Report behavior is resolved through `internal/report`.
|
||||
- Render preflight precedes Scriptorium report generation.
|
||||
- Recent Changes are computed from structured briefing snapshots.
|
||||
- Metadata links artifacts produced for a run.
|
||||
@@ -5,63 +5,58 @@ This document describes the implemented briefing package boundary.
|
||||
## Purpose
|
||||
|
||||
`internal/briefing` builds structured report-specific briefing packages from
|
||||
forecast summaries and report metadata. The package currently implements Daily
|
||||
Today, Daily Tomorrow, 3-Day Outlook, Weekend Outlook, and Storm Report
|
||||
briefing content.
|
||||
resolved report metadata, forecast bundles, and derived forecast summaries.
|
||||
Briefings are curated inputs for prompt data packages, not rendered report
|
||||
prose.
|
||||
|
||||
## Inputs and Outputs
|
||||
## Inputs And Outputs
|
||||
|
||||
Inputs:
|
||||
|
||||
- resolved report definition and valid period
|
||||
- forecast bundle
|
||||
- derived forecast summary or summaries
|
||||
- resolved report definition, generation time, timezone, and valid period
|
||||
- forecast bundle with source provenance and warnings
|
||||
- derived daily or period summaries where required
|
||||
- configured units and timezone
|
||||
|
||||
Output:
|
||||
Outputs:
|
||||
|
||||
- `briefing.Package` JSON containing common metadata and report-specific
|
||||
briefing content
|
||||
- `briefing.Package` with common metadata and one report-specific content
|
||||
object for Daily, 3-Day, Weekend, or Storm Report
|
||||
- optional JSON file written by `briefing.Save`
|
||||
|
||||
## Boundaries
|
||||
|
||||
- Briefings are structured weather facts and context for later prompt input.
|
||||
- This package does not fetch weather data, compare prior snapshots, build
|
||||
`scriptorium` data packages, or render final report prose.
|
||||
- This package selects and shapes weather facts for prompts.
|
||||
- It does not fetch weather data, compare prior snapshots, build
|
||||
`data_package` files, invoke Scriptorium, or write workflow metadata.
|
||||
|
||||
## Behavior
|
||||
## Config Fields Used
|
||||
|
||||
- Common metadata includes schema version, RunID, report ID, variant, prompt ID,
|
||||
generation time, units, timezone, valid period, source location, source
|
||||
provenance, hashes, and source warnings.
|
||||
- Daily content includes bottom-line inputs, daypart summaries, relevant alerts,
|
||||
outdoor window inputs, narrative periods, discussion context, and weather
|
||||
story context when available.
|
||||
- Daily Tomorrow also includes planning inputs for morning readiness,
|
||||
commute/school/workday concerns, and what may change overnight.
|
||||
- 3-Day content includes one summary per local day or partial day, with overall
|
||||
character, temperature range, precipitation, wind, risk, outdoor-window, and
|
||||
alert inputs, plus broader discussion and weather-story context when
|
||||
available.
|
||||
- Weekend content uses the same daily outlook summaries and adds planning
|
||||
inputs for best outdoor windows, worst weather windows, rain/storm timing,
|
||||
comfort concerns, and confidence or uncertainty context.
|
||||
- Storm content uses the explicit event window and includes event headline
|
||||
inputs, hazards, most-likely scenario inputs, reasonable worst-case inputs,
|
||||
confidence and uncertainty inputs, watch items, active alerts, relevant
|
||||
hourly and narrative forecast periods, and available discussion or weather
|
||||
story context.
|
||||
- Briefing JSON is written atomically by `briefing.Save`.
|
||||
The package receives configured units and timezone from the app layer. Daypart
|
||||
configuration is consumed by `internal/forecast` before briefing builders run.
|
||||
|
||||
## External Adapters Used
|
||||
|
||||
None directly.
|
||||
|
||||
## State Or Manifest Behavior
|
||||
|
||||
`briefing.Save` writes briefing JSON atomically. Managed workspace placement is
|
||||
owned by `internal/state`.
|
||||
|
||||
## Skip And Resume Behavior
|
||||
|
||||
None. Builders either return a complete briefing package or an error.
|
||||
|
||||
## Failure Behavior
|
||||
|
||||
- Daily briefing construction requires a Daily report definition and a derived
|
||||
daily forecast summary.
|
||||
- Daily briefing construction requires a Daily report definition and derived
|
||||
daily summary.
|
||||
- 3-Day briefing construction requires a 3-Day report definition and at least
|
||||
one derived daily summary in the outlook period.
|
||||
one derived summary.
|
||||
- Weekend briefing construction requires a Weekend report definition and at
|
||||
least one derived daily summary in the weekend period.
|
||||
- Storm briefing construction requires a Storm Report definition and a forecast
|
||||
least one derived summary.
|
||||
- Storm briefing construction requires a Storm Report definition and forecast
|
||||
bundle.
|
||||
- Save failures include path and operation context.
|
||||
|
||||
@@ -74,11 +69,11 @@ Inspect:
|
||||
- `internal/briefing/weekend_test.go`
|
||||
- `internal/briefing/storm_test.go`
|
||||
- `internal/app/app_test.go`
|
||||
- `internal/cli/root_test.go`
|
||||
|
||||
## Invariants
|
||||
|
||||
- Weather facts come from normalized and derived source data.
|
||||
- Briefing output remains JSON-inspectable.
|
||||
- LLM prompt input packaging and `scriptorium` execution remain outside this
|
||||
- Briefings contain structured weather facts and source context.
|
||||
- Common metadata includes RunID, report ID, prompt ID, valid period, source
|
||||
provenance, source hashes, and source warnings.
|
||||
- LLM prompt input packaging and Scriptorium execution remain outside this
|
||||
boundary.
|
||||
|
||||
@@ -1,62 +1,61 @@
|
||||
# Changes Internals
|
||||
|
||||
This document describes the implemented structured change comparison boundary.
|
||||
This document describes structured Recent Changes comparison.
|
||||
|
||||
## Purpose
|
||||
|
||||
`internal/changes` compares current and prior structured briefing snapshots and
|
||||
produces compact change records for prompt input data packages.
|
||||
`internal/changes` compares current and prior briefing packages and emits
|
||||
compact change records for prompt input data packages.
|
||||
|
||||
## Inputs and Outputs
|
||||
## Inputs And Outputs
|
||||
|
||||
Inputs:
|
||||
|
||||
- prior briefing package
|
||||
- current briefing package
|
||||
- configured Recent Changes thresholds
|
||||
- comparison thresholds from configuration
|
||||
|
||||
Output:
|
||||
Outputs:
|
||||
|
||||
- ordered `changes.Change` records with type, message, previous value, and
|
||||
current value where useful
|
||||
- ordered `changes.Change` items with type, message, previous value, and current
|
||||
value where useful
|
||||
|
||||
## Boundaries
|
||||
|
||||
- This package compares structured briefing data only.
|
||||
- It does not read state directly, render Markdown, invoke `scriptorium`, or
|
||||
compare generated report text.
|
||||
- It does not read filesystem state, find prior snapshots, render Markdown,
|
||||
invoke Scriptorium, or compare generated report text.
|
||||
|
||||
## Config Fields Used
|
||||
|
||||
The app maps these config fields into comparison thresholds:
|
||||
The app maps these fields into comparison thresholds:
|
||||
|
||||
- `recent_change.temperature_degrees`
|
||||
- `recent_change.precip_probability_points`
|
||||
- `recent_change.wind_gust_miles_per_hour`
|
||||
- `recent_change.precip_timing_shift_minutes`
|
||||
|
||||
## Behavior
|
||||
## External Adapters Used
|
||||
|
||||
Daily, 3-Day, and Weekend comparison currently detect:
|
||||
None.
|
||||
|
||||
- temperature changes crossing configured thresholds
|
||||
- precipitation probability and timing changes
|
||||
- alert additions and removals
|
||||
- peak wind gust changes
|
||||
- snow, ice, and thunder risk changes
|
||||
## State Or Manifest Behavior
|
||||
|
||||
When no prior comparable snapshot exists, the app sends an empty Recent Changes
|
||||
section in the data package. Daily Today and Daily Tomorrow are compatible for
|
||||
same-valid-date comparison through the report registry. 3-Day Outlook compares
|
||||
with prior 3-Day Outlook snapshots for the same valid local date. Weekend
|
||||
Outlook compares with prior Weekend Outlook snapshots for the same weekend
|
||||
window.
|
||||
None directly. The app loads prior briefing snapshots through `internal/state`
|
||||
before calling comparison functions.
|
||||
|
||||
## Skip And Resume Behavior
|
||||
|
||||
No resume behavior. When the app has no prior comparable snapshot, it sends an
|
||||
empty Recent Changes list without calling a comparison function.
|
||||
|
||||
## Failure Behavior
|
||||
|
||||
Daily comparison requires both inputs to contain Daily briefing content. 3-Day
|
||||
comparison requires both inputs to contain 3-Day briefing content. Weekend
|
||||
comparison requires both inputs to contain Weekend briefing content.
|
||||
- Daily comparison requires both inputs to contain Daily briefing content.
|
||||
- 3-Day comparison requires both inputs to contain 3-Day briefing content.
|
||||
- Weekend comparison requires both inputs to contain Weekend briefing content.
|
||||
- Storm Report currently has no comparison implementation, so the app leaves
|
||||
Recent Changes empty for Storm reports.
|
||||
|
||||
## Tests
|
||||
|
||||
@@ -70,5 +69,6 @@ Inspect:
|
||||
## Invariants
|
||||
|
||||
- Recent Changes are based on structured snapshots, not Markdown report text.
|
||||
- Comparison thresholds come from configuration.
|
||||
- The comparison output remains compact enough for prompt input.
|
||||
- Report compatibility is determined outside this package by report definitions
|
||||
and state lookup.
|
||||
- Output stays compact enough for prompt input.
|
||||
|
||||
@@ -1,57 +1,66 @@
|
||||
# Forecast Derivation Internals
|
||||
|
||||
This document describes the implemented deterministic forecast summarization
|
||||
boundary.
|
||||
This document describes deterministic forecast summarization in
|
||||
`internal/forecast`.
|
||||
|
||||
## Purpose
|
||||
|
||||
`internal/forecast` converts a normalized forecast bundle into inspectable
|
||||
daily and multi-day daypart summaries. These summaries are structured data for
|
||||
later briefing builders; they are not rendered report text.
|
||||
`internal/forecast` converts normalized bundle data into daily and period
|
||||
summaries used by briefing builders.
|
||||
|
||||
## Inputs and Outputs
|
||||
## Inputs And Outputs
|
||||
|
||||
Inputs:
|
||||
|
||||
- `forecast.Bundle`
|
||||
- local date and timezone
|
||||
- report period, for multi-day summaries
|
||||
- configured daypart definitions with `HH:MM` start and end values
|
||||
- local date or resolved report period
|
||||
- timezone
|
||||
- configured daypart definitions
|
||||
|
||||
Output:
|
||||
Outputs:
|
||||
|
||||
- `forecast.DailySummary` with a civil-day period, daypart summaries, selected
|
||||
narrative periods, alert overlaps, discussion context, source warnings, and
|
||||
source provenance.
|
||||
- `forecast.BuildPeriodDailySummaries` output with one clipped daily summary
|
||||
for each local day or partial day in a report period.
|
||||
- `forecast.DailySummary` for one local civil day
|
||||
- one clipped daily summary per local day or partial day from
|
||||
`BuildPeriodDailySummaries`
|
||||
- daypart summaries with selected hourly periods, ranges, timed maximums,
|
||||
conditions, indicators, and alert overlaps
|
||||
|
||||
## Boundaries
|
||||
|
||||
- This package groups and summarizes already-normalized forecast data.
|
||||
- It does not fetch weather data, resolve report definitions, compare prior
|
||||
snapshots, build prompt input packages, or call `scriptorium`.
|
||||
- This package groups, selects, and summarizes already-normalized forecast
|
||||
data.
|
||||
- It does not perform HTTP calls, parse CLI flags, resolve report definitions,
|
||||
compare prior snapshots, build prompt input packages, or invoke Scriptorium.
|
||||
|
||||
## Behavior
|
||||
## Config Fields Used
|
||||
|
||||
- Daypart windows use half-open intervals.
|
||||
- Overnight dayparts are supported when the end clock is not after the start
|
||||
clock.
|
||||
- Hourly forecast periods are selected by overlap with the daypart window.
|
||||
- Each daypart computes temperature range, apparent-temperature range, maximum
|
||||
precipitation probability, peak wind speed, peak wind gust, dominant
|
||||
condition, notable conditions, and basic weather indicators.
|
||||
- Alerts are selected by overlap with the daily period and each daypart.
|
||||
- Narrative periods and discussion context are selected as broader source
|
||||
context for later briefing builders.
|
||||
- Multi-day period summaries clip the first and last local days to the resolved
|
||||
report period before selecting hourly periods and alerts.
|
||||
- `dayparts[].name`
|
||||
- `dayparts[].start`
|
||||
- `dayparts[].end`
|
||||
|
||||
Threshold constants for basic indicators live in forecast code rather than
|
||||
configuration.
|
||||
|
||||
## External Adapters Used
|
||||
|
||||
None directly. Forecast data arrives through `forecast.Bundle`.
|
||||
|
||||
## State Or Manifest Behavior
|
||||
|
||||
None. Source warnings and provenance from the bundle are carried into summaries
|
||||
for later metadata and briefing output.
|
||||
|
||||
## Skip And Resume Behavior
|
||||
|
||||
None. Missing optional source context can produce empty selections, but missing
|
||||
required hourly data fails summarization.
|
||||
|
||||
## Failure Behavior
|
||||
|
||||
- Missing hourly forecast data returns an error.
|
||||
- Invalid daypart definitions return actionable parse errors.
|
||||
- Alert records without parseable RFC3339 start/end fields are skipped.
|
||||
- A nil bundle or missing hourly forecast data returns an error.
|
||||
- Invalid daypart definitions return parse errors with context.
|
||||
- Alert records without parseable RFC3339 timing are skipped.
|
||||
- Empty selected periods produce empty summaries rather than generated prose.
|
||||
|
||||
## Tests
|
||||
|
||||
@@ -62,7 +71,6 @@ Inspect:
|
||||
|
||||
## Invariants
|
||||
|
||||
- Weather facts come from normalized source data, not generated prose.
|
||||
- Outputs remain JSON-inspectable.
|
||||
- Forecast derivation remains independent of CLI, HTTP adapters, and report
|
||||
registry behavior.
|
||||
- Go owns report-period selection and meteorological summarization.
|
||||
- Weather facts come from normalized source data.
|
||||
- Outputs remain JSON-inspectable and independent of CLI, state, and adapters.
|
||||
|
||||
@@ -1,54 +1,64 @@
|
||||
# Prompt Input Internals
|
||||
|
||||
This document describes the implemented prompt input package boundary.
|
||||
This document describes prompt input data package construction.
|
||||
|
||||
## Purpose
|
||||
|
||||
`internal/promptinput` converts a structured briefing package into the
|
||||
`data_package` JSON file passed to `scriptorium` prompts.
|
||||
`internal/promptinput` converts a structured briefing package and optional
|
||||
Recent Changes into the `data_package` JSON passed to Scriptorium prompts.
|
||||
|
||||
## Inputs and Outputs
|
||||
## Inputs And Outputs
|
||||
|
||||
Input:
|
||||
Inputs:
|
||||
|
||||
- `briefing.Package` containing Daily-family, 3-Day Outlook, Weekend Outlook,
|
||||
or Storm Report content
|
||||
- `briefing.Package`
|
||||
- optional `[]changes.Change`
|
||||
|
||||
Output:
|
||||
Outputs:
|
||||
|
||||
- `promptinput.Package` JSON with report metadata, briefing content, source
|
||||
warnings, RunID, and a Recent Changes section.
|
||||
- `promptinput.Package` containing schema version, RunID, report metadata,
|
||||
briefing content, Recent Changes, and source warnings
|
||||
- optional JSON file written by `promptinput.Save`
|
||||
|
||||
## Boundaries
|
||||
|
||||
- This package owns the prompt input schema and required-field validation.
|
||||
- It does not fetch weather data, compute forecast summaries, compare prior
|
||||
snapshots, or invoke `scriptorium`.
|
||||
- This package owns the prompt input schema and validation.
|
||||
- It does not fetch weather data, derive forecast summaries, find prior
|
||||
snapshots, compare changes, or invoke Scriptorium.
|
||||
|
||||
## Behavior
|
||||
## Config Fields Used
|
||||
|
||||
- `promptinput.Build` copies report metadata from the briefing package.
|
||||
- `promptinput.Validate` rejects missing or inconsistent required fields before
|
||||
render preflight.
|
||||
- `promptinput.Save` writes JSON atomically where practical.
|
||||
- Recent Changes is present as an `items` list. It is empty when no prior
|
||||
comparable snapshot exists or no meaningful changes are detected.
|
||||
None directly. Config-derived values are already present in briefing metadata
|
||||
before this package runs.
|
||||
|
||||
## External Adapters Used
|
||||
|
||||
None.
|
||||
|
||||
## State Or Manifest Behavior
|
||||
|
||||
`promptinput.Save` writes JSON atomically. Managed workspace paths are owned by
|
||||
`internal/state`.
|
||||
|
||||
## Skip And Resume Behavior
|
||||
|
||||
None. Recent Changes is always present as an `items` list and may be empty.
|
||||
|
||||
## Failure Behavior
|
||||
|
||||
Validation errors name the missing or inconsistent field. Save failures include
|
||||
the filesystem operation and path context.
|
||||
Validation fails before render preflight when required top-level or briefing
|
||||
metadata fields are missing or inconsistent, or when no report content is
|
||||
present. Save failures include filesystem operation and path context.
|
||||
|
||||
## Tests
|
||||
|
||||
Inspect:
|
||||
|
||||
- `internal/promptinput/package_test.go`
|
||||
- `internal/changes/daily_test.go`
|
||||
- `internal/app/app_test.go`
|
||||
|
||||
## Invariants
|
||||
|
||||
- Prompt input data remains structured JSON.
|
||||
- Scriptorium receives structured `data_package` JSON.
|
||||
- Briefing metadata and top-level report metadata must agree.
|
||||
- Recent Changes is not inferred from rendered report text.
|
||||
- Recent Changes are not inferred from rendered report text.
|
||||
|
||||
@@ -1,53 +1,59 @@
|
||||
# Report Registry Internals
|
||||
|
||||
This document describes the implemented report identity and valid-period
|
||||
boundary.
|
||||
This document describes report identity, valid-period resolution, batch
|
||||
membership, and comparison declarations in `internal/report`.
|
||||
|
||||
## Purpose
|
||||
|
||||
`internal/report` centralizes report IDs, prompt IDs, comparison strategies,
|
||||
valid-period resolution, report metadata, and scheduled batch membership.
|
||||
`internal/report` centralizes report definitions so report IDs, prompt IDs,
|
||||
default output names, comparison strategies, and valid periods are declared in
|
||||
one package.
|
||||
|
||||
## Inputs and Outputs
|
||||
## Inputs And Outputs
|
||||
|
||||
Inputs:
|
||||
|
||||
- report ID or batch name
|
||||
- generation time
|
||||
- configured timezone
|
||||
- timezone
|
||||
- optional Daily date override
|
||||
- optional manual storm start and end times
|
||||
- optional Storm Report start and end times
|
||||
|
||||
Outputs:
|
||||
|
||||
- `report.Resolved` values with definition metadata and half-open valid periods
|
||||
- `report.Metadata` values suitable for later persisted run metadata
|
||||
- `report.Metadata` values used by briefing and persisted metadata builders
|
||||
|
||||
## Boundaries
|
||||
|
||||
- This package defines report identity and time coverage only.
|
||||
- It does not fetch weather data, build briefings, compare snapshots, write
|
||||
state, or call `scriptorium`.
|
||||
state, parse CLI flags, or invoke Scriptorium.
|
||||
|
||||
## Behavior
|
||||
## Config Fields Used
|
||||
|
||||
- Daily Today covers one configured local civil day.
|
||||
- Daily Tomorrow covers the next configured local civil day.
|
||||
- 3-Day Outlook covers generation time through local midnight after the second
|
||||
following local civil day.
|
||||
- Weekend Outlook covers Saturday 00:00 to Monday 00:00 Monday through
|
||||
Thursday; Friday and Saturday cover the remaining weekend from Friday 18:00
|
||||
or generation time, whichever is later.
|
||||
- Manual Storm Report uses explicit start and end times.
|
||||
- Morning batch resolves Daily Today and 3-Day Outlook, plus Weekend Outlook
|
||||
except on Sunday.
|
||||
- Evening batch resolves Daily Tomorrow.
|
||||
The app supplies `weather_api.timezone` as a loaded `time.Location`. Report
|
||||
output path copying uses default output names from report definitions.
|
||||
|
||||
## External Adapters Used
|
||||
|
||||
None.
|
||||
|
||||
## State Or Manifest Behavior
|
||||
|
||||
None directly. Resolved metadata contributes RunID, report ID, prompt ID,
|
||||
generation time, timezone, and valid period to later briefing and state
|
||||
metadata.
|
||||
|
||||
## Skip And Resume Behavior
|
||||
|
||||
No resume behavior. Morning batch resolution skips Weekend Outlook on Sunday.
|
||||
|
||||
## Failure Behavior
|
||||
|
||||
- Unknown report and batch names return actionable errors.
|
||||
- Sunday Weekend Outlook resolution returns an error.
|
||||
- Storm windows require start and end, with end after start.
|
||||
- Unknown reports and batch names return actionable errors.
|
||||
- Weekend Outlook resolution returns an error when resolved directly on Sunday.
|
||||
- Storm Report resolution requires start and end, with end after start.
|
||||
|
||||
## Tests
|
||||
|
||||
@@ -55,9 +61,11 @@ Inspect:
|
||||
|
||||
- `internal/report/period_test.go`
|
||||
- `internal/app/app_test.go`
|
||||
- `internal/cli/root_test.go`
|
||||
|
||||
## Invariants
|
||||
|
||||
- Report selection goes through the registry.
|
||||
- Valid periods are independent of rendered report text.
|
||||
- Prompt IDs and comparison strategies are declared with report definitions.
|
||||
- Daily Today and Daily Tomorrow both use `weather.daily_report`.
|
||||
- Valid periods are half-open intervals independent of rendered report text.
|
||||
- Comparison strategy is declared by report definition.
|
||||
|
||||
@@ -1,59 +1,67 @@
|
||||
# Scriptorium Adapter Internals
|
||||
|
||||
This document describes the implemented `scriptorium` subprocess adapter.
|
||||
This document describes the subprocess adapter in
|
||||
`internal/adapters/scriptorium`.
|
||||
|
||||
## Purpose
|
||||
|
||||
`internal/adapters/scriptorium` runs `scriptorium render` to preflight prompt
|
||||
wiring and `scriptorium run` to generate report artifacts.
|
||||
The adapter runs `scriptorium render` for prompt preflight and `scriptorium run`
|
||||
for Markdown report generation while isolating subprocess details from domain
|
||||
packages.
|
||||
|
||||
## Inputs and Outputs
|
||||
## Inputs And Outputs
|
||||
|
||||
Input:
|
||||
Inputs:
|
||||
|
||||
- prompt ID
|
||||
- prompt input data package path
|
||||
- report output path for `run`
|
||||
- configured binary, config path, profile, timeout, and extra arguments
|
||||
|
||||
Output:
|
||||
Outputs:
|
||||
|
||||
- captured stdout, with truncation tracking
|
||||
- captured stderr, with truncation tracking
|
||||
- argv used for execution
|
||||
- captured stdout and stderr with truncation flags
|
||||
- exit code
|
||||
- full argv used for inspection
|
||||
- report output path for `run`
|
||||
|
||||
## Boundaries
|
||||
|
||||
- This adapter owns `scriptorium` CLI flag construction and subprocess
|
||||
execution.
|
||||
- It does not choose report types, build prompt input, fetch weather data, or
|
||||
decide workflow order.
|
||||
- This adapter owns Scriptorium argv construction and subprocess execution.
|
||||
- It does not choose report types, build prompt input, fetch weather data,
|
||||
decide workflow order, or persist workflow metadata.
|
||||
|
||||
## Behavior
|
||||
## Config Fields Used
|
||||
|
||||
The render invocation shape is:
|
||||
- `scriptorium.binary`
|
||||
- `scriptorium.config_path`
|
||||
- `scriptorium.profile`
|
||||
- `scriptorium.timeout`
|
||||
- `scriptorium.extra_args`
|
||||
|
||||
```text
|
||||
scriptorium render --prompt <prompt_id> --input data_package=<path> --format json
|
||||
```
|
||||
## External Adapters Used
|
||||
|
||||
The run invocation shape is:
|
||||
- external `scriptorium` CLI
|
||||
|
||||
```text
|
||||
scriptorium run --prompt <prompt_id> --input data_package=<path> --out <artifact_path>
|
||||
```
|
||||
See [Scriptorium integration](../integrations/scriptorium.md) for the external
|
||||
CLI contract used by this project.
|
||||
|
||||
Configured `--config` and `--profile` values are added when present. Arguments
|
||||
are passed directly as argv, not through a shell. Stdout and stderr are captured
|
||||
separately. `SaveRenderResult` writes the captured result as JSON for inspection.
|
||||
## State Or Manifest Behavior
|
||||
|
||||
`SaveRenderResult` can write render results atomically. The app and state store
|
||||
own managed preflight paths and metadata links.
|
||||
|
||||
## Skip And Resume Behavior
|
||||
|
||||
None. Context cancellation and configured timeout stop subprocess execution.
|
||||
|
||||
## Failure Behavior
|
||||
|
||||
Nonzero render and run exits return both the captured result and an error
|
||||
containing the exit code and stderr. Run exit code `2` is treated as an error
|
||||
but may still produce a report artifact. Command execution respects context
|
||||
cancellation and the configured timeout.
|
||||
- Missing prompt ID, data package path, or run output path returns an error.
|
||||
- Subprocess start or context errors are wrapped with operation context.
|
||||
- Nonzero render and run exits return captured output plus an error containing
|
||||
exit code and stderr.
|
||||
- Captured stdout and stderr are size-limited and marked when truncated.
|
||||
|
||||
## Tests
|
||||
|
||||
@@ -65,7 +73,6 @@ Inspect:
|
||||
|
||||
## Invariants
|
||||
|
||||
- `scriptorium` details stay inside the adapter package.
|
||||
- The input name for prompt packages is always `data_package`.
|
||||
- Render preflight remains orchestration behavior; this adapter only exposes the
|
||||
subprocess operations.
|
||||
- No shell interpolation is used.
|
||||
- The Scriptorium input name is `data_package`.
|
||||
- Scriptorium-specific flags stay inside adapter and config boundaries.
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# State Internals
|
||||
|
||||
This document describes the implemented filesystem state boundary.
|
||||
This document describes filesystem state in `internal/state`.
|
||||
|
||||
## Purpose
|
||||
|
||||
`internal/state` owns durable artifact paths, atomic JSON writes, metadata, and
|
||||
prior comparable snapshot lookup.
|
||||
`internal/state` owns managed artifact paths, atomic JSON writes, persisted
|
||||
metadata, prior snapshot lookup, and read-only artifact inspection helpers.
|
||||
|
||||
## Inputs and Outputs
|
||||
## Inputs And Outputs
|
||||
|
||||
Inputs:
|
||||
|
||||
@@ -15,26 +15,27 @@ Inputs:
|
||||
- resolved report definition and valid period
|
||||
- briefing package
|
||||
- prompt input data package
|
||||
- `scriptorium render` result
|
||||
- rendered report path preparation
|
||||
- Scriptorium render result
|
||||
- rendered report path preparation request
|
||||
- RunID for inspection lookups
|
||||
|
||||
Outputs:
|
||||
|
||||
- briefing snapshot JSON
|
||||
- prompt input data package JSON
|
||||
- render preflight JSON
|
||||
- Markdown report path
|
||||
- metadata JSON
|
||||
- prior comparable snapshot metadata when available
|
||||
- prior briefing package when loaded by path
|
||||
- briefing snapshot JSON path
|
||||
- prompt input data package JSON path
|
||||
- render preflight JSON path
|
||||
- managed Markdown report path
|
||||
- metadata JSON path
|
||||
- prior comparable snapshot metadata
|
||||
- loaded briefing or data package
|
||||
- recent report records for inspection
|
||||
- metadata and data package lookup by RunID
|
||||
|
||||
## Boundaries
|
||||
|
||||
- This package owns managed workspace layout and narrow path validation.
|
||||
- It does not fetch weather data, derive forecasts, build prompt inputs, invoke
|
||||
`scriptorium`, or compare briefing contents.
|
||||
- This package owns managed workspace layout, path validation, filesystem
|
||||
writes, and metadata reads.
|
||||
- It does not fetch weather data, derive forecasts, build prompt input content,
|
||||
compare briefing contents, invoke Scriptorium, or parse CLI flags.
|
||||
|
||||
## Config Fields Used
|
||||
|
||||
@@ -47,25 +48,35 @@ Outputs:
|
||||
Workspace subdirectories must be relative paths that stay under
|
||||
`workspace.root`.
|
||||
|
||||
## State Behavior
|
||||
## External Adapters Used
|
||||
|
||||
Managed artifact names use RunID, which is generated from report generation time
|
||||
and report ID. Metadata is stored beside briefing snapshots by report group and
|
||||
valid local date. Prior snapshot lookup reads metadata for the same valid local
|
||||
date and returns the latest earlier compatible run. Daily Today and Daily
|
||||
Tomorrow are compatible with each other; 3-Day Outlook is compatible with prior
|
||||
3-Day Outlook snapshots; Weekend Outlook is compatible with prior Weekend
|
||||
Outlook snapshots for the same weekend window. The store can load a briefing
|
||||
snapshot by path for structured comparison. The store can list metadata-backed
|
||||
report records and load metadata or data packages by RunID for inspection. The
|
||||
store prepares the managed Markdown report path before `scriptorium run` writes
|
||||
it.
|
||||
- local filesystem
|
||||
|
||||
## State Or Manifest Behavior
|
||||
|
||||
Managed paths are grouped by report family and valid-period start date for JSON
|
||||
artifacts. Reports are written under the report group. Metadata is stored beside
|
||||
briefing snapshots and links briefing, data package, preflight, and report
|
||||
paths. Report listing walks metadata files under the snapshots directory.
|
||||
|
||||
Prior snapshot lookup reads metadata and selects the latest earlier compatible
|
||||
snapshot. Daily Today and Daily Tomorrow are compatible with each other for the
|
||||
same valid local date. 3-Day Outlook compares with prior 3-Day snapshots for
|
||||
the same valid local date. Weekend Outlook compares with prior Weekend snapshots
|
||||
for the same weekend window. Storm Report currently has no prior lookup.
|
||||
|
||||
## Skip And Resume Behavior
|
||||
|
||||
There is no resume workflow. Missing metadata directories return no inspection
|
||||
records or no prior snapshot rather than creating state.
|
||||
|
||||
## Failure Behavior
|
||||
|
||||
Writes are atomic where practical: JSON is written to a temporary file in the
|
||||
target directory and then renamed into place. Invalid workspace paths and
|
||||
missing required metadata fields produce actionable errors.
|
||||
- Invalid workspace paths return validation errors.
|
||||
- Missing required metadata fields prevent metadata writes.
|
||||
- JSON writes use a temporary file followed by rename where practical.
|
||||
- Read and decode failures include path context.
|
||||
- Unknown RunIDs produce an actionable lookup error.
|
||||
|
||||
## Tests
|
||||
|
||||
@@ -77,5 +88,5 @@ Inspect:
|
||||
## Invariants
|
||||
|
||||
- Managed paths stay under the configured workspace root.
|
||||
- Metadata links the artifacts produced for a run.
|
||||
- Metadata links artifacts produced for a run.
|
||||
- Prior lookup is based on structured metadata, not rendered report text.
|
||||
|
||||
@@ -1,59 +1,74 @@
|
||||
# Weather Data Internals
|
||||
|
||||
This document describes the implemented weather data ingestion boundary.
|
||||
This document describes Weather API ingestion into `forecast.Bundle`.
|
||||
|
||||
## Purpose
|
||||
|
||||
`internal/adapters/weatherapi` fetches normalized weather data from one
|
||||
configured weather API endpoint and assembles a `forecast.Bundle`.
|
||||
configured Weather API endpoint and assembles the bundle consumed by forecast
|
||||
derivation and briefing builders.
|
||||
|
||||
## Inputs and Outputs
|
||||
## Inputs And Outputs
|
||||
|
||||
Input:
|
||||
Inputs:
|
||||
|
||||
- `config.Config` with `weather_api.base_url`, `format`, `units`, `timezone`,
|
||||
`precision`, timeout, and missing-source policy.
|
||||
- `config.Config` with Weather API URL, timeout, format, units, timezone,
|
||||
precision, and missing-source policy
|
||||
- HTTP responses using the Weather API `data` envelope
|
||||
|
||||
Output:
|
||||
Outputs:
|
||||
|
||||
- `forecast.Bundle` containing observation, current conditions, hourly forecast,
|
||||
narrative forecast, alerts, discussion, stub source slots, provenance, and
|
||||
source warnings.
|
||||
- `forecast.Bundle` with observation, current conditions, hourly forecast,
|
||||
narrative forecast, active alerts, discussion, source records, and source
|
||||
warnings
|
||||
- stub source records for daily forecast and weather story source slots
|
||||
- optional saved bundle JSON through app fetch helpers
|
||||
|
||||
## Boundaries
|
||||
|
||||
- The adapter performs HTTP calls and decoding only.
|
||||
- Forecast derivation, daypart grouping, report periods, report rendering, and
|
||||
`scriptorium` execution are outside this boundary.
|
||||
- Hourly forecast data is required. Other missing or malformed source sections
|
||||
use the configured missing-source policy.
|
||||
- The adapter owns HTTP calls, response-envelope handling, source hashing, and
|
||||
decoding into internal bundle types.
|
||||
- It does not derive dayparts, resolve report periods, build briefings, compare
|
||||
snapshots, write report state, or invoke Scriptorium.
|
||||
|
||||
## External Adapter
|
||||
## Config Fields Used
|
||||
|
||||
The adapter calls:
|
||||
- `weather_api.base_url`
|
||||
- `weather_api.timeout`
|
||||
- `weather_api.format`
|
||||
- `weather_api.units`
|
||||
- `weather_api.timezone`
|
||||
- `weather_api.precision`
|
||||
- `missing_source.default`
|
||||
- `missing_source.sources`
|
||||
|
||||
- `/observations`
|
||||
- `/conditions/current`
|
||||
- `/forecast/hourly`
|
||||
- `/forecast/narrative`
|
||||
- `/alerts/active`
|
||||
- `/discussion`
|
||||
## External Adapters Used
|
||||
|
||||
Forecast routes use the full-product endpoints, not day-slice endpoints.
|
||||
- Weather API HTTP service
|
||||
|
||||
## State
|
||||
See [Weather API integration](../integrations/weatherapi.md) for the external
|
||||
contract used by this project.
|
||||
|
||||
`app.FetchAndSaveBundle` can save an inspectable bundle JSON file using an
|
||||
atomic rename. No report state, snapshots, or prompt input packages are written
|
||||
yet.
|
||||
## State Or Manifest Behavior
|
||||
|
||||
The adapter records source name, endpoint, query, fetch time, source timestamps
|
||||
when available, SHA-256 hash over compact raw `data` JSON, missing status, and
|
||||
source warnings. `app.FetchAndSaveBundle` can write bundle JSON atomically for
|
||||
inspection.
|
||||
|
||||
## Skip And Resume Behavior
|
||||
|
||||
No resume behavior. Optional missing or malformed sources may be omitted,
|
||||
warned, or treated as errors according to missing-source policy. Hourly forecast
|
||||
data is required and cannot be skipped.
|
||||
|
||||
## Failure Behavior
|
||||
|
||||
- HTTP and envelope decode failures return actionable errors with endpoint
|
||||
context.
|
||||
- Missing hourly data fails the fetch.
|
||||
- Missing or malformed optional sources follow `error`, `warn`, or `none`.
|
||||
- Source identity uses SHA-256 over compacted raw `data` JSON.
|
||||
- Missing or invalid `weather_api.base_url` prevents client construction.
|
||||
- HTTP errors, response read failures, and envelope decode failures include
|
||||
endpoint context.
|
||||
- Missing hourly data or hourly forecasts with no periods fail bundle fetch.
|
||||
- Optional and stub sources follow missing-source policy.
|
||||
|
||||
## Tests
|
||||
|
||||
@@ -65,5 +80,6 @@ Inspect:
|
||||
## Invariants
|
||||
|
||||
- Weather facts come from normalized source data.
|
||||
- External API details stay inside `internal/adapters/weatherapi`.
|
||||
- Source provenance and warnings remain inspectable for later briefing builders.
|
||||
- Full hourly and narrative products are fetched; Go owns report-period
|
||||
selection.
|
||||
- Source provenance and warnings remain inspectable downstream.
|
||||
|
||||
Reference in New Issue
Block a user