Document stateless output operations

This commit is contained in:
2026-08-01 20:11:57 +00:00
parent 97215ddb9b
commit bd34ec57f8
8 changed files with 183 additions and 322 deletions

View File

@@ -1,17 +1,17 @@
# Weatherreporter CLI
`weatherreporter` generates weather reports, runs report batches, and inspects
artifacts already stored in its workspace.
`weatherreporter` generates Markdown weather reports and runs report batches.
It has no command for inspecting prior runs or application-owned state.
## Shortest Useful Command
```sh
weatherreporter generate today --out ./today.md
weatherreporter generate today
```
The command uses the configured Weather API and writes an extra Markdown copy
at `./today.md`. See the [configuration reference](config.md) to supply the
required Weather API endpoint.
The command uses the configured Weather API and writes an atomically replaced
`today.md` in the current directory. See the [configuration reference](config.md)
to supply the required Weather API endpoint.
## Commands And Usage
@@ -24,12 +24,6 @@ weatherreporter generate tomorrow [--config PATH] [--units VALUE] [--tz NAME] [-
weatherreporter generate hourly [--config PATH] [--units VALUE] [--tz NAME] [--out PATH] [--llm-debug-dir PATH] [--quiet]
weatherreporter run morning [--config PATH] [--units VALUE] [--tz NAME] [--out-dir PATH] [--llm-debug-dir PATH] [--quiet]
weatherreporter run evening [--config PATH] [--units VALUE] [--tz NAME] [--out-dir PATH] [--llm-debug-dir PATH] [--quiet]
weatherreporter inspect reports [--config PATH] [--limit N]
weatherreporter inspect metadata [--config PATH] RUN_ID
weatherreporter inspect modules [--config PATH] RUN_ID
weatherreporter inspect data-package [--config PATH] RUN_ID
weatherreporter inspect prior [--config PATH] RUN_ID
weatherreporter inspect sources [--config PATH] RUN_ID
```
`weatherreporter --version` prints the version embedded in the executable.
@@ -38,69 +32,78 @@ builds report `development`.
| Command | Contract |
| --- | --- |
| `generate daily` | Requires `--date YYYY-MM-DD`; the date is interpreted in the effective report timezone. |
| `generate today` | Accepts an optional `--date YYYY-MM-DD`; without it, the current local date in the effective report timezone is used. |
| `generate tomorrow` | Uses the next local civil day and accepts the common generate flags. |
| `generate hourly` | Covers the next six hours in the effective report timezone. It does not accept `--date`, `--hours`, or `--duration`. |
| `run morning` and `run evening` | Run their defined report batches. `--out-dir` writes extra Markdown copies; `--out` is not accepted. |
| `generate daily` | Requires `--date YYYY-MM-DD`; the date is interpreted in the effective report timezone. Its default filename is `daily-YYYY-MM-DD.md`. |
| `generate today` | Accepts an optional `--date YYYY-MM-DD`; without it, the current local date in the effective report timezone is used. Its default filename is `today.md`. |
| `generate tomorrow` | Uses the next local civil day and writes `tomorrow.md` by default. |
| `generate hourly` | Covers the next six hours in the effective report timezone and writes `hourly.md` by default. It does not accept `--date`, `--hours`, or `--duration`. |
| `run morning` and `run evening` | Run their defined report batches and write each selected report beneath the current directory unless `--out-dir` selects another directory. `--out` is not accepted. |
`generate` accepts the four report command names shown above. `run` accepts
only `morning` and `evening`. Batch membership, workspace artifacts, and
notification sequencing are described in the [operations guide](operations.md).
only `morning` and `evening`. Batch membership and notification ordering are
described in the [operations guide](operations.md).
## Output, Errors, And Quiet Mode
For `generate`, the default output is the report's filename in the current
directory. `--out PATH` selects one output file instead. A relative path is
resolved from the current directory; an absolute path is used as given. For a
batch, the equivalent default is the current directory and `--out-dir PATH`
selects its output directory. Successful summaries always report the resulting
absolute `outputPath` values.
Outputs are written atomically. A generation, rendering, write, or cancellation
failure before publication leaves an existing destination unchanged. A
notification failure occurs after publication, so the newly written output
remains available.
Action commands (`generate` and `run`) write a JSON summary to stdout unless
`--quiet` is set. `run` also writes compact per-report and batch status lines
to stderr. A pre-run error, such as an invalid flag, missing required argument,
or configuration-load failure, produces no partial JSON summary. When an action
fails after it has produced a result, its summary has `"status": "failed"` and
an `error` field.
or configuration-load failure, produces no partial JSON summary. When an
action fails after it has produced a result, its summary has `"status": "failed"`
and an `error` field.
`--quiet` is supported by action commands only. It suppresses action summaries
and routine batch status output; it does not suppress command errors.
Inspection commands always write their requested JSON value to stdout and do
not accept `--quiet`.
### Generate Summary
A generate summary always identifies the command, report, run, generation
time, valid period, and status:
A generate summary identifies the command, report, run, generation time, valid
period, prompt version, timezone, and status. Successful output has an absolute
`outputPath`:
```json
{
"command": "generate",
"reportId": "today",
"reportName": "Today Report",
"promptId": "weather.today_generated_text",
"promptVersion": "2.0.0",
"runId": "20260529T120000.000000000Z_today",
"status": "succeeded",
"generatedAt": "2026-05-29T12:00:00Z",
"validPeriod": {
"start": "2026-05-29T00:00:00-05:00",
"end": "2026-05-30T00:00:00-05:00"
}
"timezone": "America/Chicago",
"outputPath": "/srv/weather/today.md"
}
```
When available, the summary also includes `reportPath`, `metadataPath`,
`dataPackagePath`, `preparationPath`, `executionPath`, `generatedTextRawPath`,
`generatedTextPath`, `renderContextPath`, and `llmDebugPath`. `outputPath` is included only
when `--out` wrote an extra copy. Distributor notification, when attempted,
adds `notificationPath` and may add a compact `notification` object.
When available, the summary also includes the effective `profileId`,
`backendId`, `modelName`, `sourceWarnings`, `validationStatus`, requested
`llmDebugPath`, and compact Distributor `notification` result. It does not
include historical or transient artifact paths such as metadata, prompt input,
raw generated text, render context, or notification receipts.
### Run Summary And Stderr
A run summary contains `command`, `batch`, `status`, `startedAt`, `finishedAt`,
`total`, `succeeded`, `failed`, and a `reports` array. It may also contain a
top-level `notification` object and `error`. Batch status is `failed` if any
report or the batch notification fails.
`total`, `succeeded`, `failed`, and a `reports` array. Each report item includes
its identity, status, effective profile and model details when available,
source warnings, validation status, and absolute `outputPath` after publication.
The top-level summary may also contain a batch `notification` object and
`error`. Batch status is `failed` if any report or the batch notification fails.
Without `--quiet`, batch status lines use this form:
```text
report=today status=succeeded output="reports/today.md"
report=today status=succeeded output="/srv/weather/reports/today.md"
batch=morning total=2 succeeded=2 failed=0
```
@@ -112,12 +115,11 @@ batch=morning total=2 succeeded=2 failed=0
| `--config PATH` | all commands | Load `PATH` instead of `/usr/local/etc/weatherreporter/config.yml`. |
| `--units VALUE` | `generate`, `run` | Override `weather_api.units` for this command. |
| `--tz NAME` | `generate`, `run` | Override `weather_api.timezone` for this command. |
| `--out PATH` | every `generate` command | Write an extra Markdown report copy. |
| `--llm-debug-dir PATH` | every `generate` and `run` command | Write requested sensitive prompt diagnostics outside the managed workspace. The path must be absolute. |
| `--out-dir PATH` | `run morning`, `run evening` | Write extra Markdown report copies in `PATH`. |
| `--out PATH` | every `generate` command | Write the report to this file instead of its current-directory default. |
| `--llm-debug-dir PATH` | every `generate` and `run` command | Write requested sensitive prompt diagnostics under this absolute path. |
| `--out-dir PATH` | `run morning`, `run evening` | Write batch reports beneath this directory instead of the current directory. |
| `--quiet` | `generate`, `run` | Suppress action summaries and routine batch status output. |
| `--date YYYY-MM-DD` | `generate daily`, `generate today` | Required for Daily; optional for Today. |
| `--limit N` | `inspect reports` | Maximum runs to list. Defaults to `20`; `0` means no limit. |
Distributor notification is configured through `notify.distributor`; there are
no Distributor-specific CLI flags. See the [configuration reference](config.md).
@@ -125,33 +127,9 @@ no Distributor-specific CLI flags. See the [configuration reference](config.md).
## Invocation Examples
```sh
weatherreporter generate daily --date 2026-05-29 --out ./daily.md
weatherreporter generate today --date 2026-05-29 --out ./today.md
weatherreporter generate hourly --out ./hourly.md
weatherreporter generate daily --date 2026-05-29
weatherreporter generate today --out ./reports/today.md
weatherreporter generate hourly --out /srv/weather/hourly.md
weatherreporter generate today --llm-debug-dir /var/tmp/weatherreporter-debug
weatherreporter run morning --out-dir ./reports --llm-debug-dir /var/tmp/weatherreporter-debug
```
## Inspection Commands
```sh
weatherreporter inspect reports --limit 10
weatherreporter inspect metadata 20260529T100000.000000000Z_today
weatherreporter inspect modules 20260529T100000.000000000Z_today
weatherreporter inspect data-package 20260529T100000.000000000Z_today
weatherreporter inspect prior 20260529T100000.000000000Z_today
weatherreporter inspect sources 20260529T100000.000000000Z_today
```
| Command | JSON returned |
| --- | --- |
| `inspect reports` | Recent generated runs, including artifact paths and source-warning counts. |
| `inspect metadata RUN_ID` | Persisted metadata for the run. |
| `inspect modules RUN_ID` | The run's persisted ordered module snapshot. |
| `inspect data-package RUN_ID` | The run's persisted prompt data package. |
| `inspect prior RUN_ID` | Prior comparable snapshot metadata, or `null` when none exists. |
| `inspect sources RUN_ID` | Source provenance and source warnings without full weather payloads. |
Inspection is read-only: it does not collect weather data or invoke Promptkit.
See the [operations guide](operations.md) for artifact lifecycle
and recovery.

View File

@@ -13,8 +13,8 @@ explicit `--config PATH` must exist. Values are applied in this order:
2. the configuration file, when present; and
3. the `--units` and `--tz` command-line overrides.
Environment variables do not override configuration fields. Output flags write
extra report copies for a command and do not change configuration.
Environment variables do not override configuration fields. Output flags select
operator-owned destinations for one command and do not change configuration.
## Maintained Examples
@@ -129,7 +129,7 @@ The default paths are:
| `tomorrow` | `daily/{valid_start_date}/{run_id}.md`, `daily/{valid_start_date}/index.md`, `tomorrow/index.md` |
See the [operations guide](operations.md) for notification timing, uploaded
artifact selection, and failure handling.
output selection, and failure handling.
### `missing_source`
@@ -160,7 +160,7 @@ individual `generate` or `run` command when explicitly needed.
`profile` selects an ID; `profile_file` and `profile_dir` supply definitions.
They are separate decisions. An explicit `profile` applies to every selected
report. Otherwise Hourly selects `weather-light`, while Daily, Today, and
Tomorrow select `weather-balanced` through their exact `1.1.0` prompt
Tomorrow select `weather-balanced` through their exact `2.0.0` prompt
definitions.
Promptkit resolves a selected profile definition from a test or embedding
@@ -179,21 +179,6 @@ model before use. An alternative profile may use `backend: local`; in that
case `promptkit.local.endpoint` supplies the conventional local backend
endpoint.
### `workspace`
| Field | Default |
| --- | --- |
| `root` | `workspace` |
| `snapshots_dir` | `snapshots` |
| `reports_dir` | `reports` |
| `data_packages_dir` | `data-packages` |
| `preflight_dir` | `preflight` |
| `notifications_dir` | `notifications` |
`workspace.root` is required. Each workspace subdirectory must be a relative
path that stays within the root. See the [operations guide](operations.md) for
the managed workspace layout and lifecycle.
### `dayparts`
`dayparts` is a non-empty list of named local-time windows used in forecast
@@ -202,18 +187,6 @@ derivation. Every item needs `name`, `start`, and `end`; start and end use
(`06:00``10:00`), `midday` (`10:00``15:00`), `afternoon`
(`15:00``17:00`), and `evening` (`17:00``24:00`).
### `recent_change`
| Field | Default |
| --- | --- |
| `temperature_degrees` | `5` |
| `precip_probability_points` | `20` |
| `wind_gust_miles_per_hour` | `10` |
| `precip_timing_shift_minutes` | `120` |
These thresholds control when Recent Changes are included in prompt input for a
prior comparable module snapshot.
### `reports`
`reports` optionally overrides a report's ordered deterministic modules and

View File

@@ -21,16 +21,15 @@ boundaries and invariants.
| Adding, changing, reviewing, or deleting tests | [Testing policy](policy/testing.md) and focused package tests | The policy defines risk-based sufficiency, durable test boundaries, doubles, and test-maintenance criteria. |
| CLI commands, flags, output, quiet mode, or command wiring | [CLI reference](cli.md) and [CLI internals](internal/cli.md) | The reference owns the user contract; the internal guide owns command composition and output flow. |
| Configuration fields, defaults, loading, overrides, validation, or secrets | [Configuration reference](config.md), [architecture policy](policy/architecture.md), and tests under `internal/config` | These separate the user-visible contract, architectural rules, and executable behavior. |
| Top-level generation, batch, collection, inspection, or notification workflow | [App orchestration internals](internal/app-orchestration.md) | It owns workflow ordering, persistence points, failure propagation, and orchestration invariants. |
| Top-level generation, batch, collection, output publication, or notification workflow | [App orchestration internals](internal/app-orchestration.md) | It owns workflow ordering, output publication, failure propagation, and orchestration invariants. |
| Weather API transport, source envelopes, source warnings, or collection | [Weather API integration](integrations/weatherapi.md), [weather-data internals](internal/weather-data.md), and [collection internals](internal/collect.md) | These separate the external contract, normalized source facts, and app-facing collection behavior. |
| Forecast periods, weather derivation, collected facts, or derived facts | [Forecast derivation internals](internal/forecast-derivation.md) and [fact contracts](internal/facts.md) | They own deterministic derivation and the fact boundaries used by reports. |
| Report definitions, valid periods, report IDs, output naming, or batch composition | [Report registry internals](internal/report-registry.md) and [app orchestration internals](internal/app-orchestration.md) | Report definitions own selection and period rules; orchestration owns execution. |
| Module IDs, module composition, briefing values, or prompt-facing exports | [Module contract internals](internal/module.md), [module builder internals](internal/briefing.md), and [prompt-input internals](internal/prompt-input.md) | These own module contracts, value construction, and the curated prompt-package boundary. |
| Recent Changes comparison | [Changes internals](internal/changes.md) and [operations guide](operations.md) | The internal guide owns structured comparison; operations owns user-visible artifact behavior. |
| Prompt execution, profiles, prompt inputs, or result handling | `internal/promptexec`, the Promptkit adapter, and [prompt-input internals](internal/prompt-input.md) | These separate the executor contract and input construction. |
| Generated-text schemas, validation, render contexts, templates, or Markdown rendering | [Generated-text internals](internal/generatedtext.md), [report-template internals](internal/reporttemplate.md), and [report template guide](templates.md) | These own structured text, renderer implementation, and the maintainer-facing template surface. |
| Workspace paths, metadata, atomic persistence, lookup, inspection, diagnosis, or recovery | [State internals](internal/state.md) and [operations guide](operations.md) | These separate implementation behavior from operator workflows, diagnosis, and recovery. |
| Distributor bundles, uploads, notification artifacts, or failures | [Distributor adapter internals](internal/distributor-adapter.md), [Distributor integration contracts](integrations/distributor/), and [operations guide](operations.md) | These separate adapter behavior, external contracts, and operational lifecycle. |
| Output destinations, atomic publication, prompt diagnosis, or legacy cleanup | [Operations guide](operations.md) and [App orchestration internals](internal/app-orchestration.md) | Operations owns operator workflows; app internals owns the implementation boundary. |
| Distributor bundles, uploads, notification results, or failures | [Distributor adapter internals](internal/distributor-adapter.md), [Distributor integration contracts](integrations/distributor/), and [operations guide](operations.md) | These separate adapter behavior, external contracts, and operational lifecycle. |
| Maintained example configuration | [Configuration reference](config.md) and files under `examples/` | The reference owns field meaning; examples own complete copyable files. |
| Release preparation, tagging, publication, or verification | [Release procedure](release.md) | It owns version selection, release-note preparation, candidate validation, tag publication, CI behavior, and post-publication checks. |
| Proposed, deferred, or unimplemented work | Documents under `docs/roadmap/` | Future behavior and implementation status belong only in roadmaps until implemented. |
@@ -45,13 +44,13 @@ present before introducing a new package or abstraction.
| --- | --- |
| `cmd/weatherreporter` | Binary entry point. |
| `internal/cli` | Command parsing, flags, help, output, and command wiring. |
| `internal/app` | Generation, batches, collection coordination, notification, and inspection orchestration. |
| `internal/app` | Stateless generation, batches, collection coordination, output publication, and notification. |
| `internal/config` | Configuration defaults, loading, precedence, secrets, and validation. |
| `internal/adapters` | Weather API, Promptkit, and Distributor boundaries. |
| `internal/weatherdata`, `internal/forecast`, `internal/facts` | Normalized source facts and deterministic derivation. |
| `internal/report`, `internal/module`, `internal/briefing`, `internal/changes` | Report registry, module contracts and values, and structured comparison. |
| `internal/promptinput`, `internal/generatedtext`, `internal/reporttemplate` | Prompt packages, generated-text validation, render contexts, and Markdown templates. |
| `internal/state`, `internal/fileutil`, `internal/timeutil` | Durable artifacts, atomic file operations, clocks, dates, timezones, and periods. |
| `internal/fileutil`, `internal/timeutil` | Atomic output operations, clocks, dates, timezones, and periods. |
| `docs` | User, operator, integration, internal, policy, and roadmap documentation. |
| `examples` | Maintained copyable configuration. |

View File

@@ -1,30 +1,59 @@
# Weatherreporter Operations
This guide covers normal operation, managed workspace state, inspection,
recovery, and operational caveats. See the [CLI reference](cli.md) for complete
command syntax and the [configuration reference](config.md) for fields,
defaults, and notification templates.
This guide covers normal output handling, Distributor notification, secure
prompt diagnostics, and cleanup of legacy application state. See the [CLI
reference](cli.md) for command syntax and the [configuration reference](config.md)
for fields, defaults, and notification templates.
## Normal Operation
After configuring a Weather API endpoint, generate one report:
```sh
weatherreporter generate today --out ./today.md
weatherreporter generate today
```
A generation collects weather data, resolves the report period, builds and
persists the module snapshot and prompt data package, records Promptkit
preparation provenance before provider execution, then persists raw output and
execution provenance, validates the structured generated text, and renders the
managed Markdown report from the validated text and deterministic values.
These receipts describe the current workspace implementation; they are not a
cross-version profile-provenance contract.
The command writes `today.md` in the current directory. Choose a different
operator-owned file with `--out`; a relative path is resolved from the current
directory and an absolute path is used directly. Weatherreporter renders in
memory and atomically replaces the selected destination only after generation
and rendering succeed. It does not create a default workspace, metadata,
receipts, or intermediate output files.
The managed report and its final metadata are saved before single-report
Distributor notification is attempted. `--out` writes an extra operator copy;
it never changes the managed report or upload source. A successful generate
command prints its summary to stdout unless `--quiet` is used.
Before a destination is published, provider, validation, rendering, write, and
cancellation failures leave an existing report unchanged. A notification
failure happens after publication, so retain and use the completed Markdown
file while resolving the delivery error. The JSON result identifies the
absolute output path and active profile, backend, model, warnings, validation,
debug, and notification information; see the [CLI reference](cli.md) for its
exact fields.
## Batch Outputs And Distributor Notification
Run a scheduled batch with an explicit output directory when appropriate:
```sh
weatherreporter run morning --out-dir ./reports
```
Without `--out-dir`, batch reports are written beneath the current directory.
Morning runs Today, Tomorrow, and every eligible dated Daily Report; evening
runs Tomorrow and the same eligible Daily Reports. Eligible Daily dates begin
after tomorrow and require complete hourly coverage for their local civil day.
A batch collects once, processes each selected report independently, and keeps
successful outputs if another report fails.
When `notify.distributor.enabled` and batch notification are enabled,
Weatherreporter sends one Distributor upload only after every selected output
exists. If an item fails, the batch notification is skipped and successful
files remain at their selected destinations. A batch notification failure also
leaves all successfully published report files in place. Distributor source
files are those operator-owned Markdown outputs; rendered bundle paths and
delivery status appear in the result, not in a local notification receipt.
For a single report, Distributor notification follows the atomic output write.
See the [configuration reference](config.md) for pipeline, bundle,
idempotency-key, and per-report path templates.
## Local Prompt Profile Override
@@ -36,20 +65,11 @@ set its `endpoint` and `model` for the local server, and configure the copy as
completely replaces the embedded definition; it does not affect a report that
selects another profile ID.
For example, install the profile file at a known absolute path and set:
```yaml
promptkit:
profile_file: /etc/weatherreporter/weather-light-local-profile.yml
```
Prompt inspection occurs before weather collection. A malformed profile file,
missing required credential, or unsupported selected backend stops the command
before collection. A reachable profile can still fail later if its local model
endpoint is unavailable; Weatherreporter does not switch to a remote profile.
See the [configuration reference](config.md) for field definitions. For a
provider failure, start with the command error and enable secure prompt debug
capture when content-rich diagnostics are required.
Prompt and profile validation occurs before weather collection. A malformed
profile file, missing required credential, or unsupported selected backend
stops the command before collection. A reachable profile can still fail later
if its local model endpoint is unavailable; Weatherreporter does not switch to
a remote profile.
## Optional Prompt Debug Capture
@@ -59,153 +79,41 @@ Use `--llm-debug-dir` only when content-rich prompt diagnostics are required:
weatherreporter generate today --llm-debug-dir /var/tmp/weatherreporter-debug
```
The directory must be absolute and is initialized before prompt inspection or
weather collection. Capture files are stored outside the managed workspace,
with restrictive permissions, under the report ID, valid date, and RunID.
They can contain rendered prompts and generated output, so the normal metadata,
CLI summary, and routine logs contain only the optional directory path—not
their content. A capture-write failure stops that run before later work can
continue.
The directory must be absolute. Requested captures are written with restrictive
permissions beneath the supplied directory, organized by report and run. They
can contain rendered prompts and generated output, so limit access to trusted
operators and remove the captures when they are no longer needed. Normal output,
summaries, and routine logs omit that sensitive content. Debug capture is never
created for an ordinary command without `--llm-debug-dir`.
Run a scheduled batch with the same configured collection:
If capture creation or writing fails, the affected run fails rather than
silently continuing without the requested diagnostics.
## Diagnosing Failures
Start with the command error and JSON summary. For a report generation failure,
the selected destination was not replaced; for a notification failure, inspect
the completed destination and the notification result. For a batch failure,
use the per-report statuses and retain successful output files. Enable explicit
debug capture only when content-rich Promptkit diagnostics are necessary.
Weatherreporter does not retain runs for later inspection, resume failed work,
or provide automatic cleanup, archival, remote state, daemon operation, or
automatic storm monitoring.
## Manual Cleanup Of Legacy Workspaces
Older installations may have a directory named `workspace` containing reports,
snapshots, prompt inputs, or notification records from previous versions.
Current commands neither read nor update it. After confirming that no separate
retention requirement applies, remove that specific legacy directory manually;
do not use a broad cleanup command that could remove current operator outputs.
For example, from the directory that contains the old directory:
```sh
weatherreporter run morning --out-dir ./reports --llm-debug-dir /var/tmp/weatherreporter-debug
rm -rf ./workspace
```
Each batch validates its configured prompt/profile candidates, then collects once before it plans reports. Morning runs Today, Tomorrow,
and every eligible dated Daily Report; evening runs Tomorrow and the same
eligible Daily Reports. Eligible Daily dates begin after tomorrow and require
complete hourly coverage for their entire local civil day. A batch continues
after an individual report fails and returns an aggregate failure when any
report or batch notification fails.
`--out-dir` writes extra copies such as `today.md`, `tomorrow.md`, and
`daily-YYYY-MM-DD.md`. These copies are never upload sources. Batch report
copies and notification behavior are summarized in the CLI result; use the
[CLI reference](cli.md) for its exact JSON and stderr contract.
## Managed Workspace
The default workspace root is `workspace`. Artifact paths use the report
definition's artifact group, the valid-period start date in the effective
timezone, and the RunID:
```text
workspace/
reports/<artifact_group>/<YYYY-MM-DD>/report.<run_id>.md
snapshots/<artifact_group>/<YYYY-MM-DD>/modules.<run_id>.json
snapshots/<artifact_group>/<YYYY-MM-DD>/metadata.<run_id>.json
snapshots/<artifact_group>/<YYYY-MM-DD>/generated_text_raw.<run_id>.json
snapshots/<artifact_group>/<YYYY-MM-DD>/prompt_execution.<run_id>.json
snapshots/<artifact_group>/<YYYY-MM-DD>/generated_text.<run_id>.json
snapshots/<artifact_group>/<YYYY-MM-DD>/render_context.<run_id>.json
data-packages/<artifact_group>/<YYYY-MM-DD>/data_package.<run_id>.yaml
preflight/<artifact_group>/<YYYY-MM-DD>/prompt_preparation.<run_id>.json
notifications/<artifact_group>/<YYYY-MM-DD>/distributor.<run_id>.json
notifications/batches/<batch>/<YYYY-MM-DD>/distributor.<batch_run_id>.json
```
The generated-text and render-context artifacts are written for every completed
single-report generation.
A report's metadata links the module snapshot, data package, preparation and
execution receipts, managed report, generated-text artifacts, and any available single-report
notification artifact. These current-version receipts are implementation
details rather than durable interfaces. Use the active command's error and
explicit secure debug capture for prompt diagnosis. Batch
notification artifacts are separate batch-level records under
`notifications/batches`.
RunIDs begin with the UTC generation timestamp and report ID. A Daily RunID
also contains its local valid date so multiple Daily reports in one batch have
different managed paths. Batch notification RunIDs contain the UTC batch start
timestamp and batch name.
## Distributor Notification
When `notify.distributor.enabled` is enabled, a successful `generate`
uploads only the managed Markdown report after final metadata has been saved.
The extra copy from `--out` is never uploaded. A notification attempt writes
a redacted debug artifact at
`notifications/<artifact_group>/<YYYY-MM-DD>/distributor.<run_id>.json`; its
path is then recorded in report metadata.
Batches suppress per-report notification. When both Distributor and its batch
notification are enabled, Weatherreporter submits one multi-report upload after
every planned report succeeds. If any report fails, it records a top-level
`skipped` notification with reason `one or more reports failed` and does not
call Distributor. If batch notification is disabled, a batch does not fall back
to individual uploads.
A batch notification attempt writes
`notifications/batches/<batch>/<YYYY-MM-DD>/distributor.<batch_run_id>.json`.
A notification failure makes the batch fail but does not change successful
individual report items into failed items. The debug artifacts contain rendered
identifiers, managed source and bundle paths, upload and status results, and
redacted errors; they do not contain tokens.
## Inspecting Stored Runs
Inspection is read-only: it neither collects weather data nor invokes
Promptkit or Distributor. Start by finding a RunID:
```sh
weatherreporter inspect reports --limit 10
weatherreporter inspect metadata RUN_ID
```
| Command | Reads |
| --- | --- |
| `inspect reports` | Metadata files under the workspace snapshots tree. |
| `inspect metadata RUN_ID` | Metadata located by RunID. |
| `inspect modules RUN_ID` | The module snapshot path recorded in metadata. |
| `inspect data-package RUN_ID` | The data-package path recorded in metadata. |
| `inspect prior RUN_ID` | The run metadata, then compatible earlier metadata for its comparison policy. |
| `inspect sources RUN_ID` | Source provenance and warnings in the run metadata. |
A missing snapshots directory produces no listed reports. An unknown or empty
RunID is an error; use `inspect reports` to obtain a valid value.
New runs write `weatherreporter.metadata.v2`, including preparation and
execution references once those receipts exist. `inspect metadata` also reads
historic V1 records; their legacy preflight and generated-text-result fields
remain visible for compatibility, but Weatherreporter does not write them for
new runs.
## Recovery
Keep the workspace when a run fails: artifacts reached before the failure
remain available where they can be safely persisted.
- A preparation failure can leave its classified receipt and metadata.
- A report-generation failure can leave the managed report, module snapshot,
data package, and metadata.
- A completed prompt validation rejection leaves raw text, an execution receipt,
and metadata. Later generated-text failures can also leave validated text and
a render-context artifact, depending on where they stopped.
- A single-report notification failure preserves the report and final metadata,
including its notification artifact when it was written.
- A batch notification failure preserves each report's artifacts and adds the
top-level batch notification artifact.
Use the action summary and its error first. For prompt or provider
diagnosis, prefer an explicitly enabled secure debug capture; current-version
receipt paths may provide supplemental context when available. For a batch
failure, inspect the summary first, then inspect the affected report RunIDs or
the batch notification path. Do not remove the whole workspace as a first
response; retain it until the failure is understood.
## Operational Caveats
- Workspace files and generated reports can contain
sensitive operational context. Set appropriate filesystem permissions and do
not publish them unintentionally.
- Weatherreporter uses one configured Weather API endpoint and local workspace
state.
- Promptkit profile resolution does not discover local endpoints or fail over
between local and remote profiles.
- It does not provide automatic resume, cleanup, archival, remote state, daemon
operation, or automatic storm monitoring.
This removal cannot be recovered by Weatherreporter. Keep or archive any
historical files that are still needed before deleting them.

View File

@@ -10,9 +10,10 @@ package inventory; focused documents in `docs/internal/` own implementation deta
Weatherreporter is a deterministic weather-report CLI. It collects normalized
weather data, derives facts and modules, builds a curated YAML data package,
compares prior snapshots, executes exact-version Promptkit prompts, validates
structured generated prose, and renders repository-owned Markdown. Completed
managed Markdown may be uploaded through Distributor.
executes exact-version Promptkit prompts, validates structured generated prose,
and renders repository-owned Markdown in memory. Completed Markdown is
atomically published to an operator-owned output destination and may then be
uploaded through Distributor.
The supported report products are Daily, Today, Tomorrow, and Hourly. A batch
collects once, validates its complete candidate prompt/profile set before
@@ -25,14 +26,12 @@ after every planned report succeeds.
- `internal/cli` owns command parsing, help, summaries, and one executor
construction per action.
- `internal/config` owns defaults, loading, validation, and secret loading.
- `internal/app` owns workflow order, partial results, and notification
coordination through project-owned contracts.
- `internal/app` owns in-memory workflow order, partial results, atomic output
publication, and notification coordination through project-owned contracts.
- Deterministic domain packages own weather derivation, report periods, modules,
generated-text validation, and template contexts.
- `internal/adapters/weatherapi`, `internal/adapters/promptkit`, and
`internal/adapters/distributor` own their external dependency mechanics.
- `internal/state` owns workspace paths, V2 metadata, atomic persistence, and
read-only inspection.
Dependency-specific Promptkit types remain inside its adapter. The application
does not parse flags, construct provider clients, or render provider output
@@ -41,28 +40,29 @@ directly.
## Prompt Execution Invariants
- Prompts receive curated module packages, never unbounded raw weather payloads.
- Every execution inspects the exact prompt version and output contract before
- Every execution validates the exact prompt version and output contract before
collection. The selected profile is configured explicitly or declared by the
prompt; unsupported direct-key profiles and missing reported credentials fail
before collection.
- Prepared execution persists safe preparation provenance before provider work.
Completed execution persists safe execution provenance; raw output is
validated before template rendering.
- Prompt and profile validation completes before weather collection. Raw output
is validated before template rendering.
- Generated text fills defined prose slots only. Deterministic facts remain
authoritative and repository-owned templates produce all managed Markdown.
- Sensitive rendered prompts, schemas, input bodies, provider endpoints, and
credentials never enter normal metadata, summaries, logs, or workspace
artifacts. They are written only to an explicit secure debug root when
requested.
credentials never enter normal summaries or logs. They are written only to
an explicit secure debug root when requested.
## State, Notification, And Testing Invariants
## Output, Notification, And Testing Invariants
- Managed writes are atomic where practical and stay beneath the configured
workspace root. Reached artifacts remain inspectable after later failures.
- New records use `weatherreporter.metadata.v2`; V1 records remain readable for
inspection compatibility.
- Distributor uploads use only the managed Markdown report, never output copies
or workspace scans. Notification follows report and final metadata success.
- Normal execution is stateless: it keeps weather data, prompt input, generated
text, and render context in memory and creates no application-owned durable
state.
- Markdown writes are atomic at an operator-selected destination. A
pre-publication failure does not replace an existing destination; a
notification failure does not remove a newly published output.
- Distributor uploads use only the published Markdown output, never a scan of
local files. Single notification follows publication; batch notification
follows publication of every selected report.
- Default tests are deterministic, offline, and use Promptkit/provider fakes
rather than live provider calls. See the [testing policy](testing.md).

View File

@@ -85,8 +85,8 @@ mechanisms, not secret values.
| Release procedure | `docs/release.md` | Version policy, release preparation, validation, tagging, automated publication, verification, failure handling, and release ordering. | General contributor workflow, product contracts, release-specific change summaries, and implementation history. |
| Release notes | `docs/releases/` | One versioned, changelog-style summary for each release, including compatibility and operator action. The file at the tagged commit supplies the corresponding Gitea release body. | Current CLI, configuration, operations, integration, architecture, and internal contracts; release procedure; implementation plans. |
| CLI contract | `docs/cli.md` | Commands, arguments, flags, invocation semantics, stdout and stderr behavior, summaries, and exit behavior. | Configuration field definitions, complete operating procedures, runtime filesystem layout, and command implementation. |
| Configuration contract | `docs/config.md` | Discovery and precedence, fields, defaults, secrets, validation rules, and user-selectable values. | Complete example files, CLI syntax, runtime state lifecycle, and loading implementation. |
| Operations | `docs/operations.md` | Normal workflows, physical workspace layout, artifacts and metadata, inspection, notification behavior, diagnosis, recovery, cleanup, permissions, and operational caveats. | Complete CLI syntax, configuration field definitions, logical external contracts, and implementation mechanics. |
| Configuration contract | `docs/config.md` | Discovery and precedence, fields, defaults, secrets, validation rules, and user-selectable values. | Complete example files, CLI syntax, output lifecycle, and loading implementation. |
| Operations | `docs/operations.md` | Normal output handling, atomic replacement, notification behavior, diagnosis, explicit debug capture, manual legacy-workspace cleanup, permissions, and operational caveats. | Complete CLI syntax, configuration field definitions, logical external contracts, and implementation mechanics. |
| Report template surface | `docs/templates.md` | Implemented template files and partials, render-context fields, editing rules, and maintainer-facing template examples. | Weather derivation, module implementation, generated-text validation internals, and operator procedures. |
| External and durable integration contracts | `docs/integrations/` | Weather API, Promptkit, Distributor, external formats and protocols, durable logical paths and schemas, compatibility behavior, and upstream or downstream responsibilities. | Physical runtime placement and lifecycle, internal transformations, CLI syntax, and configuration defaults. |
| Internal subsystem behavior | `docs/internal/` | Implementation flow, internal collaborators and state transitions, package-local guarantees and failures, and relevant tests. | Global architecture invariants, user-facing contracts, external schemas, operator procedures, and future package plans. |
@@ -113,8 +113,8 @@ parallel package or behavior references.
CLI documentation answers how to invoke Weatherreporter and what its command
interface does. Configuration documentation answers what settings mean.
Operations answers what happens to runtime state and how to operate or recover
the application, including diagnosis and safe responses to runtime failures.
Operations answers how to handle operator-owned outputs and runtime failures,
including diagnosis, explicit debug capture, and safe legacy cleanup.
When a workflow crosses these topics, place the complete procedure with the
document that owns the task and link to the other contracts. Do not duplicate

View File

@@ -96,8 +96,8 @@ Use each test type where it protects a distinct risk:
- Integration tests use real deterministic collaborators when correctness
depends on their interaction, while replacing live or nondeterministic
external boundaries.
- App and CLI tests protect representative assembled generation, batch,
inspection, persistence, and notification workflows.
- App and CLI tests protect representative assembled generation, batch, atomic
output, and notification workflows.
- Fixtures must be minimal, synthetic, versioned with the behavior they
exercise, and free of credentials or private data.
- Golden files are appropriate only when the complete output is intentionally
@@ -199,9 +199,9 @@ Each behavior should have a clear test owner:
- Config tests own loading, precedence, defaults, secrets, and validation.
- Domain tests own weather transformations and invariants.
- Adapter tests own HTTP, Promptkit/provider, and upload boundaries.
- Orchestrator tests own workflow ordering, persistence, partial success, and
failure propagation.
- State tests own path derivation, atomic artifacts, lookup, and round trips.
- Orchestrator tests own workflow ordering, output publication, partial success,
and failure propagation.
- Filesystem tests own atomic writes and destination-preservation behavior.
- Template and generated-text tests own schemas, render contexts, and rendered
output contracts.
@@ -219,8 +219,8 @@ observation:
3. Use stubs when a dependency only needs controlled responses.
4. Use mocks when the interaction itself is contractual.
Mocks are appropriate for requirements such as uploading exactly once, saving
metadata before notification, propagating cancellation to Promptkit, or
Mocks are appropriate for requirements such as uploading exactly once,
notifying only after output publication, propagating cancellation to Promptkit, or
avoiding an external call after an earlier workflow failure. Do not use mocks
merely to isolate every object or reproduce the implementation's call graph.