Document internal component boundaries

This commit is contained in:
2026-05-29 19:54:22 +00:00
parent f23af43013
commit 4f530b2b6a
9 changed files with 407 additions and 263 deletions

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

View File

@@ -5,63 +5,58 @@ This document describes the implemented briefing package boundary.
## Purpose ## Purpose
`internal/briefing` builds structured report-specific briefing packages from `internal/briefing` builds structured report-specific briefing packages from
forecast summaries and report metadata. The package currently implements Daily resolved report metadata, forecast bundles, and derived forecast summaries.
Today, Daily Tomorrow, 3-Day Outlook, Weekend Outlook, and Storm Report Briefings are curated inputs for prompt data packages, not rendered report
briefing content. prose.
## Inputs and Outputs ## Inputs And Outputs
Inputs: Inputs:
- resolved report definition and valid period - resolved report definition, generation time, timezone, and valid period
- forecast bundle - forecast bundle with source provenance and warnings
- derived forecast summary or summaries - derived daily or period summaries where required
- configured units and timezone - configured units and timezone
Output: Outputs:
- `briefing.Package` JSON containing common metadata and report-specific - `briefing.Package` with common metadata and one report-specific content
briefing content object for Daily, 3-Day, Weekend, or Storm Report
- optional JSON file written by `briefing.Save`
## Boundaries ## Boundaries
- Briefings are structured weather facts and context for later prompt input. - This package selects and shapes weather facts for prompts.
- This package does not fetch weather data, compare prior snapshots, build - It does not fetch weather data, compare prior snapshots, build
`scriptorium` data packages, or render final report prose. `data_package` files, invoke Scriptorium, or write workflow metadata.
## Behavior ## Config Fields Used
- Common metadata includes schema version, RunID, report ID, variant, prompt ID, The package receives configured units and timezone from the app layer. Daypart
generation time, units, timezone, valid period, source location, source configuration is consumed by `internal/forecast` before briefing builders run.
provenance, hashes, and source warnings.
- Daily content includes bottom-line inputs, daypart summaries, relevant alerts, ## External Adapters Used
outdoor window inputs, narrative periods, discussion context, and weather
story context when available. None directly.
- Daily Tomorrow also includes planning inputs for morning readiness,
commute/school/workday concerns, and what may change overnight. ## State Or Manifest Behavior
- 3-Day content includes one summary per local day or partial day, with overall
character, temperature range, precipitation, wind, risk, outdoor-window, and `briefing.Save` writes briefing JSON atomically. Managed workspace placement is
alert inputs, plus broader discussion and weather-story context when owned by `internal/state`.
available.
- Weekend content uses the same daily outlook summaries and adds planning ## Skip And Resume Behavior
inputs for best outdoor windows, worst weather windows, rain/storm timing,
comfort concerns, and confidence or uncertainty context. None. Builders either return a complete briefing package or an error.
- 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`.
## Failure Behavior ## Failure Behavior
- Daily briefing construction requires a Daily report definition and a derived - Daily briefing construction requires a Daily report definition and derived
daily forecast summary. daily summary.
- 3-Day briefing construction requires a 3-Day report definition and at least - 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 - Weekend briefing construction requires a Weekend report definition and at
least one derived daily summary in the weekend period. least one derived summary.
- Storm briefing construction requires a Storm Report definition and a forecast - Storm briefing construction requires a Storm Report definition and forecast
bundle. bundle.
- Save failures include path and operation context. - Save failures include path and operation context.
@@ -74,11 +69,11 @@ Inspect:
- `internal/briefing/weekend_test.go` - `internal/briefing/weekend_test.go`
- `internal/briefing/storm_test.go` - `internal/briefing/storm_test.go`
- `internal/app/app_test.go` - `internal/app/app_test.go`
- `internal/cli/root_test.go`
## Invariants ## Invariants
- Weather facts come from normalized and derived source data. - Briefings contain structured weather facts and source context.
- Briefing output remains JSON-inspectable. - Common metadata includes RunID, report ID, prompt ID, valid period, source
- LLM prompt input packaging and `scriptorium` execution remain outside this provenance, source hashes, and source warnings.
- LLM prompt input packaging and Scriptorium execution remain outside this
boundary. boundary.

View File

@@ -1,62 +1,61 @@
# Changes Internals # Changes Internals
This document describes the implemented structured change comparison boundary. This document describes structured Recent Changes comparison.
## Purpose ## Purpose
`internal/changes` compares current and prior structured briefing snapshots and `internal/changes` compares current and prior briefing packages and emits
produces compact change records for prompt input data packages. compact change records for prompt input data packages.
## Inputs and Outputs ## Inputs And Outputs
Inputs: Inputs:
- prior briefing package - prior briefing package
- current 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 - ordered `changes.Change` items with type, message, previous value, and current
current value where useful value where useful
## Boundaries ## Boundaries
- This package compares structured briefing data only. - This package compares structured briefing data only.
- It does not read state directly, render Markdown, invoke `scriptorium`, or - It does not read filesystem state, find prior snapshots, render Markdown,
compare generated report text. invoke Scriptorium, or compare generated report text.
## Config Fields Used ## 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.temperature_degrees`
- `recent_change.precip_probability_points` - `recent_change.precip_probability_points`
- `recent_change.wind_gust_miles_per_hour` - `recent_change.wind_gust_miles_per_hour`
- `recent_change.precip_timing_shift_minutes` - `recent_change.precip_timing_shift_minutes`
## Behavior ## External Adapters Used
Daily, 3-Day, and Weekend comparison currently detect: None.
- temperature changes crossing configured thresholds ## State Or Manifest Behavior
- precipitation probability and timing changes
- alert additions and removals
- peak wind gust changes
- snow, ice, and thunder risk changes
When no prior comparable snapshot exists, the app sends an empty Recent Changes None directly. The app loads prior briefing snapshots through `internal/state`
section in the data package. Daily Today and Daily Tomorrow are compatible for before calling comparison functions.
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 ## Skip And Resume Behavior
Outlook compares with prior Weekend Outlook snapshots for the same weekend
window. 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 ## Failure Behavior
Daily comparison requires both inputs to contain Daily briefing content. 3-Day - Daily comparison requires both inputs to contain Daily briefing content.
comparison requires both inputs to contain 3-Day briefing content. Weekend - 3-Day comparison requires both inputs to contain 3-Day briefing content.
comparison requires both inputs to contain Weekend 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 ## Tests
@@ -70,5 +69,6 @@ Inspect:
## Invariants ## Invariants
- Recent Changes are based on structured snapshots, not Markdown report text. - Recent Changes are based on structured snapshots, not Markdown report text.
- Comparison thresholds come from configuration. - Report compatibility is determined outside this package by report definitions
- The comparison output remains compact enough for prompt input. and state lookup.
- Output stays compact enough for prompt input.

View File

@@ -1,57 +1,66 @@
# Forecast Derivation Internals # Forecast Derivation Internals
This document describes the implemented deterministic forecast summarization This document describes deterministic forecast summarization in
boundary. `internal/forecast`.
## Purpose ## Purpose
`internal/forecast` converts a normalized forecast bundle into inspectable `internal/forecast` converts normalized bundle data into daily and period
daily and multi-day daypart summaries. These summaries are structured data for summaries used by briefing builders.
later briefing builders; they are not rendered report text.
## Inputs and Outputs ## Inputs And Outputs
Inputs: Inputs:
- `forecast.Bundle` - `forecast.Bundle`
- local date and timezone - local date or resolved report period
- report period, for multi-day summaries - timezone
- configured daypart definitions with `HH:MM` start and end values - configured daypart definitions
Output: Outputs:
- `forecast.DailySummary` with a civil-day period, daypart summaries, selected - `forecast.DailySummary` for one local civil day
narrative periods, alert overlaps, discussion context, source warnings, and - one clipped daily summary per local day or partial day from
source provenance. `BuildPeriodDailySummaries`
- `forecast.BuildPeriodDailySummaries` output with one clipped daily summary - daypart summaries with selected hourly periods, ranges, timed maximums,
for each local day or partial day in a report period. conditions, indicators, and alert overlaps
## Boundaries ## Boundaries
- This package groups and summarizes already-normalized forecast data. - This package groups, selects, and summarizes already-normalized forecast
- It does not fetch weather data, resolve report definitions, compare prior data.
snapshots, build prompt input packages, or call `scriptorium`. - 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. - `dayparts[].name`
- Overnight dayparts are supported when the end clock is not after the start - `dayparts[].start`
clock. - `dayparts[].end`
- Hourly forecast periods are selected by overlap with the daypart window.
- Each daypart computes temperature range, apparent-temperature range, maximum Threshold constants for basic indicators live in forecast code rather than
precipitation probability, peak wind speed, peak wind gust, dominant configuration.
condition, notable conditions, and basic weather indicators.
- Alerts are selected by overlap with the daily period and each daypart. ## External Adapters Used
- Narrative periods and discussion context are selected as broader source
context for later briefing builders. None directly. Forecast data arrives through `forecast.Bundle`.
- Multi-day period summaries clip the first and last local days to the resolved
report period before selecting hourly periods and alerts. ## 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 ## Failure Behavior
- Missing hourly forecast data returns an error. - A nil bundle or missing hourly forecast data returns an error.
- Invalid daypart definitions return actionable parse errors. - Invalid daypart definitions return parse errors with context.
- Alert records without parseable RFC3339 start/end fields are skipped. - Alert records without parseable RFC3339 timing are skipped.
- Empty selected periods produce empty summaries rather than generated prose.
## Tests ## Tests
@@ -62,7 +71,6 @@ Inspect:
## Invariants ## Invariants
- Weather facts come from normalized source data, not generated prose. - Go owns report-period selection and meteorological summarization.
- Outputs remain JSON-inspectable. - Weather facts come from normalized source data.
- Forecast derivation remains independent of CLI, HTTP adapters, and report - Outputs remain JSON-inspectable and independent of CLI, state, and adapters.
registry behavior.

View File

@@ -1,54 +1,64 @@
# Prompt Input Internals # Prompt Input Internals
This document describes the implemented prompt input package boundary. This document describes prompt input data package construction.
## Purpose ## Purpose
`internal/promptinput` converts a structured briefing package into the `internal/promptinput` converts a structured briefing package and optional
`data_package` JSON file passed to `scriptorium` prompts. 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, - `briefing.Package`
or Storm Report content - optional `[]changes.Change`
Output: Outputs:
- `promptinput.Package` JSON with report metadata, briefing content, source - `promptinput.Package` containing schema version, RunID, report metadata,
warnings, RunID, and a Recent Changes section. briefing content, Recent Changes, and source warnings
- optional JSON file written by `promptinput.Save`
## Boundaries ## Boundaries
- This package owns the prompt input schema and required-field validation. - This package owns the prompt input schema and validation.
- It does not fetch weather data, compute forecast summaries, compare prior - It does not fetch weather data, derive forecast summaries, find prior
snapshots, or invoke `scriptorium`. snapshots, compare changes, or invoke Scriptorium.
## Behavior ## Config Fields Used
- `promptinput.Build` copies report metadata from the briefing package. None directly. Config-derived values are already present in briefing metadata
- `promptinput.Validate` rejects missing or inconsistent required fields before before this package runs.
render preflight.
- `promptinput.Save` writes JSON atomically where practical. ## External Adapters Used
- Recent Changes is present as an `items` list. It is empty when no prior
comparable snapshot exists or no meaningful changes are detected. 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 ## Failure Behavior
Validation errors name the missing or inconsistent field. Save failures include Validation fails before render preflight when required top-level or briefing
the filesystem operation and path context. metadata fields are missing or inconsistent, or when no report content is
present. Save failures include filesystem operation and path context.
## Tests ## Tests
Inspect: Inspect:
- `internal/promptinput/package_test.go` - `internal/promptinput/package_test.go`
- `internal/changes/daily_test.go`
- `internal/app/app_test.go` - `internal/app/app_test.go`
## Invariants ## Invariants
- Prompt input data remains structured JSON. - Scriptorium receives structured `data_package` JSON.
- Briefing metadata and top-level report metadata must agree. - 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.

View File

@@ -1,53 +1,59 @@
# Report Registry Internals # Report Registry Internals
This document describes the implemented report identity and valid-period This document describes report identity, valid-period resolution, batch
boundary. membership, and comparison declarations in `internal/report`.
## Purpose ## Purpose
`internal/report` centralizes report IDs, prompt IDs, comparison strategies, `internal/report` centralizes report definitions so report IDs, prompt IDs,
valid-period resolution, report metadata, and scheduled batch membership. default output names, comparison strategies, and valid periods are declared in
one package.
## Inputs and Outputs ## Inputs And Outputs
Inputs: Inputs:
- report ID or batch name - report ID or batch name
- generation time - generation time
- configured timezone - timezone
- optional Daily date override - optional Daily date override
- optional manual storm start and end times - optional Storm Report start and end times
Outputs: Outputs:
- `report.Resolved` values with definition metadata and half-open valid periods - `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 ## Boundaries
- This package defines report identity and time coverage only. - This package defines report identity and time coverage only.
- It does not fetch weather data, build briefings, compare snapshots, write - 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. The app supplies `weather_api.timezone` as a loaded `time.Location`. Report
- Daily Tomorrow covers the next configured local civil day. output path copying uses default output names from report definitions.
- 3-Day Outlook covers generation time through local midnight after the second
following local civil day. ## External Adapters Used
- Weekend Outlook covers Saturday 00:00 to Monday 00:00 Monday through
Thursday; Friday and Saturday cover the remaining weekend from Friday 18:00 None.
or generation time, whichever is later.
- Manual Storm Report uses explicit start and end times. ## State Or Manifest Behavior
- Morning batch resolves Daily Today and 3-Day Outlook, plus Weekend Outlook
except on Sunday. None directly. Resolved metadata contributes RunID, report ID, prompt ID,
- Evening batch resolves Daily Tomorrow. 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 ## Failure Behavior
- Unknown report and batch names return actionable errors. - Unknown reports and batch names return actionable errors.
- Sunday Weekend Outlook resolution returns an error. - Weekend Outlook resolution returns an error when resolved directly on Sunday.
- Storm windows require start and end, with end after start. - Storm Report resolution requires start and end, with end after start.
## Tests ## Tests
@@ -55,9 +61,11 @@ Inspect:
- `internal/report/period_test.go` - `internal/report/period_test.go`
- `internal/app/app_test.go` - `internal/app/app_test.go`
- `internal/cli/root_test.go`
## Invariants ## Invariants
- Report selection goes through the registry. - Report selection goes through the registry.
- Valid periods are independent of rendered report text. - Daily Today and Daily Tomorrow both use `weather.daily_report`.
- Prompt IDs and comparison strategies are declared with report definitions. - Valid periods are half-open intervals independent of rendered report text.
- Comparison strategy is declared by report definition.

View File

@@ -1,59 +1,67 @@
# Scriptorium Adapter Internals # Scriptorium Adapter Internals
This document describes the implemented `scriptorium` subprocess adapter. This document describes the subprocess adapter in
`internal/adapters/scriptorium`.
## Purpose ## Purpose
`internal/adapters/scriptorium` runs `scriptorium render` to preflight prompt The adapter runs `scriptorium render` for prompt preflight and `scriptorium run`
wiring and `scriptorium run` to generate report artifacts. for Markdown report generation while isolating subprocess details from domain
packages.
## Inputs and Outputs ## Inputs And Outputs
Input: Inputs:
- prompt ID - prompt ID
- prompt input data package path - prompt input data package path
- report output path for `run` - report output path for `run`
- configured binary, config path, profile, timeout, and extra arguments - configured binary, config path, profile, timeout, and extra arguments
Output: Outputs:
- captured stdout, with truncation tracking - argv used for execution
- captured stderr, with truncation tracking - captured stdout and stderr with truncation flags
- exit code - exit code
- full argv used for inspection - report output path for `run`
## Boundaries ## Boundaries
- This adapter owns `scriptorium` CLI flag construction and subprocess - This adapter owns Scriptorium argv construction and subprocess execution.
execution. - It does not choose report types, build prompt input, fetch weather data,
- It does not choose report types, build prompt input, fetch weather data, or decide workflow order, or persist workflow metadata.
decide workflow order.
## Behavior ## Config Fields Used
The render invocation shape is: - `scriptorium.binary`
- `scriptorium.config_path`
- `scriptorium.profile`
- `scriptorium.timeout`
- `scriptorium.extra_args`
```text ## External Adapters Used
scriptorium render --prompt <prompt_id> --input data_package=<path> --format json
```
The run invocation shape is: - external `scriptorium` CLI
```text See [Scriptorium integration](../integrations/scriptorium.md) for the external
scriptorium run --prompt <prompt_id> --input data_package=<path> --out <artifact_path> CLI contract used by this project.
```
Configured `--config` and `--profile` values are added when present. Arguments ## State Or Manifest Behavior
are passed directly as argv, not through a shell. Stdout and stderr are captured
separately. `SaveRenderResult` writes the captured result as JSON for inspection. `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 ## Failure Behavior
Nonzero render and run exits return both the captured result and an error - Missing prompt ID, data package path, or run output path returns an error.
containing the exit code and stderr. Run exit code `2` is treated as an error - Subprocess start or context errors are wrapped with operation context.
but may still produce a report artifact. Command execution respects context - Nonzero render and run exits return captured output plus an error containing
cancellation and the configured timeout. exit code and stderr.
- Captured stdout and stderr are size-limited and marked when truncated.
## Tests ## Tests
@@ -65,7 +73,6 @@ Inspect:
## Invariants ## Invariants
- `scriptorium` details stay inside the adapter package. - No shell interpolation is used.
- The input name for prompt packages is always `data_package`. - The Scriptorium input name is `data_package`.
- Render preflight remains orchestration behavior; this adapter only exposes the - Scriptorium-specific flags stay inside adapter and config boundaries.
subprocess operations.

View File

@@ -1,13 +1,13 @@
# State Internals # State Internals
This document describes the implemented filesystem state boundary. This document describes filesystem state in `internal/state`.
## Purpose ## Purpose
`internal/state` owns durable artifact paths, atomic JSON writes, metadata, and `internal/state` owns managed artifact paths, atomic JSON writes, persisted
prior comparable snapshot lookup. metadata, prior snapshot lookup, and read-only artifact inspection helpers.
## Inputs and Outputs ## Inputs And Outputs
Inputs: Inputs:
@@ -15,26 +15,27 @@ Inputs:
- resolved report definition and valid period - resolved report definition and valid period
- briefing package - briefing package
- prompt input data package - prompt input data package
- `scriptorium render` result - Scriptorium render result
- rendered report path preparation - rendered report path preparation request
- RunID for inspection lookups
Outputs: Outputs:
- briefing snapshot JSON - briefing snapshot JSON path
- prompt input data package JSON - prompt input data package JSON path
- render preflight JSON - render preflight JSON path
- Markdown report path - managed Markdown report path
- metadata JSON - metadata JSON path
- prior comparable snapshot metadata when available - prior comparable snapshot metadata
- prior briefing package when loaded by path - loaded briefing or data package
- recent report records for inspection - recent report records for inspection
- metadata and data package lookup by RunID
## Boundaries ## Boundaries
- This package owns managed workspace layout and narrow path validation. - This package owns managed workspace layout, path validation, filesystem
- It does not fetch weather data, derive forecasts, build prompt inputs, invoke writes, and metadata reads.
`scriptorium`, or compare briefing contents. - It does not fetch weather data, derive forecasts, build prompt input content,
compare briefing contents, invoke Scriptorium, or parse CLI flags.
## Config Fields Used ## Config Fields Used
@@ -47,25 +48,35 @@ Outputs:
Workspace subdirectories must be relative paths that stay under Workspace subdirectories must be relative paths that stay under
`workspace.root`. `workspace.root`.
## State Behavior ## External Adapters Used
Managed artifact names use RunID, which is generated from report generation time - local filesystem
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 ## State Or Manifest Behavior
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 Managed paths are grouped by report family and valid-period start date for JSON
3-Day Outlook snapshots; Weekend Outlook is compatible with prior Weekend artifacts. Reports are written under the report group. Metadata is stored beside
Outlook snapshots for the same weekend window. The store can load a briefing briefing snapshots and links briefing, data package, preflight, and report
snapshot by path for structured comparison. The store can list metadata-backed paths. Report listing walks metadata files under the snapshots directory.
report records and load metadata or data packages by RunID for inspection. The
store prepares the managed Markdown report path before `scriptorium run` writes Prior snapshot lookup reads metadata and selects the latest earlier compatible
it. 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 ## Failure Behavior
Writes are atomic where practical: JSON is written to a temporary file in the - Invalid workspace paths return validation errors.
target directory and then renamed into place. Invalid workspace paths and - Missing required metadata fields prevent metadata writes.
missing required metadata fields produce actionable errors. - 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 ## Tests
@@ -77,5 +88,5 @@ Inspect:
## Invariants ## Invariants
- Managed paths stay under the configured workspace root. - 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. - Prior lookup is based on structured metadata, not rendered report text.

View File

@@ -1,59 +1,74 @@
# Weather Data Internals # Weather Data Internals
This document describes the implemented weather data ingestion boundary. This document describes Weather API ingestion into `forecast.Bundle`.
## Purpose ## Purpose
`internal/adapters/weatherapi` fetches normalized weather data from one `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`, - `config.Config` with Weather API URL, timeout, format, units, timezone,
`precision`, timeout, and missing-source policy. precision, and missing-source policy
- HTTP responses using the Weather API `data` envelope
Output: Outputs:
- `forecast.Bundle` containing observation, current conditions, hourly forecast, - `forecast.Bundle` with observation, current conditions, hourly forecast,
narrative forecast, alerts, discussion, stub source slots, provenance, and narrative forecast, active alerts, discussion, source records, and source
source warnings. warnings
- stub source records for daily forecast and weather story source slots
- optional saved bundle JSON through app fetch helpers
## Boundaries ## Boundaries
- The adapter performs HTTP calls and decoding only. - The adapter owns HTTP calls, response-envelope handling, source hashing, and
- Forecast derivation, daypart grouping, report periods, report rendering, and decoding into internal bundle types.
`scriptorium` execution are outside this boundary. - It does not derive dayparts, resolve report periods, build briefings, compare
- Hourly forecast data is required. Other missing or malformed source sections snapshots, write report state, or invoke Scriptorium.
use the configured missing-source policy.
## 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` ## External Adapters Used
- `/conditions/current`
- `/forecast/hourly`
- `/forecast/narrative`
- `/alerts/active`
- `/discussion`
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 ## State Or Manifest Behavior
atomic rename. No report state, snapshots, or prompt input packages are written
yet. 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 ## Failure Behavior
- HTTP and envelope decode failures return actionable errors with endpoint - Missing or invalid `weather_api.base_url` prevents client construction.
context. - HTTP errors, response read failures, and envelope decode failures include
- Missing hourly data fails the fetch. endpoint context.
- Missing or malformed optional sources follow `error`, `warn`, or `none`. - Missing hourly data or hourly forecasts with no periods fail bundle fetch.
- Source identity uses SHA-256 over compacted raw `data` JSON. - Optional and stub sources follow missing-source policy.
## Tests ## Tests
@@ -65,5 +80,6 @@ Inspect:
## Invariants ## Invariants
- Weather facts come from normalized source data. - Weather facts come from normalized source data.
- External API details stay inside `internal/adapters/weatherapi`. - Full hourly and narrative products are fetched; Go owns report-period
- Source provenance and warnings remain inspectable for later briefing builders. selection.
- Source provenance and warnings remain inspectable downstream.