From b96f40e5ca563e3613cc98cb6e7de48a4bfff78f Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Fri, 31 Jul 2026 05:03:02 +0000 Subject: [PATCH] Document Promptkit report generation --- docs/cli.md | 12 +- docs/config.md | 16 +- docs/development.md | 4 +- docs/integrations/promptkit.md | 22 ++ docs/integrations/scriptorium.md | 90 ------ docs/internal/app-orchestration.md | 145 ++------- docs/internal/briefing.md | 2 +- docs/internal/cli.md | 85 ++---- docs/internal/collect.md | 2 +- docs/internal/generatedtext.md | 2 +- docs/internal/prompt-input.md | 4 +- docs/internal/promptkit-adapter.md | 24 ++ docs/internal/report-registry.md | 2 +- docs/internal/reporttemplate.md | 32 +- docs/internal/scriptorium-adapter.md | 51 ---- docs/internal/state.md | 114 ++----- docs/operations.md | 14 +- docs/policy/architecture.md | 251 ++++----------- docs/policy/documentation.md | 2 +- docs/policy/testing.md | 12 +- .../prompts/common/data_package.user.md | 107 ------- .../scriptorium/prompts/common/system.md | 9 - .../daily/daily_generated_text.user.md | 63 ---- .../prompts/daily/daily_generated_text.yml | 25 -- .../daily_report/daily_report.system.md | 13 - .../prompts/daily_report/daily_report.user.md | 234 -------------- .../prompts/daily_report/daily_report.yml | 24 -- .../hourly/hourly_generated_text.user.md | 55 ---- .../prompts/hourly/hourly_generated_text.yml | 25 -- .../today/today_generated_text.user.md | 57 ---- .../prompts/today/today_generated_text.yml | 25 -- .../tomorrow/tomorrow_generated_text.user.md | 58 ---- .../tomorrow/tomorrow_generated_text.yml | 25 -- .../daily/daily.generated_text.schema.json | 26 -- .../hourly/hourly.generated_text.schema.json | 22 -- .../today/today.generated_text.schema.json | 26 -- .../tomorrow.generated_text.schema.json | 26 -- docs/templates.md | 4 +- docs/troubleshooting.md | 287 ++---------------- 39 files changed, 256 insertions(+), 1741 deletions(-) create mode 100644 docs/integrations/promptkit.md delete mode 100644 docs/integrations/scriptorium.md create mode 100644 docs/internal/promptkit-adapter.md delete mode 100644 docs/internal/scriptorium-adapter.md delete mode 100644 docs/roadmap/scriptorium/prompts/common/data_package.user.md delete mode 100644 docs/roadmap/scriptorium/prompts/common/system.md delete mode 100644 docs/roadmap/scriptorium/prompts/daily/daily_generated_text.user.md delete mode 100644 docs/roadmap/scriptorium/prompts/daily/daily_generated_text.yml delete mode 100644 docs/roadmap/scriptorium/prompts/daily_report/daily_report.system.md delete mode 100644 docs/roadmap/scriptorium/prompts/daily_report/daily_report.user.md delete mode 100644 docs/roadmap/scriptorium/prompts/daily_report/daily_report.yml delete mode 100644 docs/roadmap/scriptorium/prompts/hourly/hourly_generated_text.user.md delete mode 100644 docs/roadmap/scriptorium/prompts/hourly/hourly_generated_text.yml delete mode 100644 docs/roadmap/scriptorium/prompts/today/today_generated_text.user.md delete mode 100644 docs/roadmap/scriptorium/prompts/today/today_generated_text.yml delete mode 100644 docs/roadmap/scriptorium/prompts/tomorrow/tomorrow_generated_text.user.md delete mode 100644 docs/roadmap/scriptorium/prompts/tomorrow/tomorrow_generated_text.yml delete mode 100644 docs/roadmap/scriptorium/schemas/daily/daily.generated_text.schema.json delete mode 100644 docs/roadmap/scriptorium/schemas/hourly/hourly.generated_text.schema.json delete mode 100644 docs/roadmap/scriptorium/schemas/today/today.generated_text.schema.json delete mode 100644 docs/roadmap/scriptorium/schemas/tomorrow/tomorrow.generated_text.schema.json diff --git a/docs/cli.md b/docs/cli.md index 6d795b5..6279d03 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -21,8 +21,8 @@ weatherreporter generate daily --date YYYY-MM-DD [--config PATH] [--units VALUE] weatherreporter generate today [--config PATH] [--units VALUE] [--tz NAME] [--out PATH] [--date YYYY-MM-DD] [--llm-debug-dir PATH] [--quiet] weatherreporter generate tomorrow [--config PATH] [--units VALUE] [--tz NAME] [--out PATH] [--llm-debug-dir PATH] [--quiet] 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] [--quiet] -weatherreporter run evening [--config PATH] [--units VALUE] [--tz NAME] [--out-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 @@ -108,7 +108,7 @@ batch=morning total=2 succeeded=2 failed=0 | `--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` command | Write requested sensitive prompt diagnostics outside the managed workspace. The path must be absolute. | +| `--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`. | | `--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. | @@ -124,7 +124,7 @@ 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 today --llm-debug-dir /var/tmp/weatherreporter-debug -weatherreporter run morning --out-dir ./reports +weatherreporter run morning --out-dir ./reports --llm-debug-dir /var/tmp/weatherreporter-debug ``` ## Inspection Commands @@ -147,6 +147,6 @@ weatherreporter inspect sources 20260529T100000.000000000Z_today | `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 -`scriptorium`. See the [operations guide](operations.md) for artifact lifecycle +Inspection is read-only: it does not collect weather data or invoke Promptkit. +See the [operations guide](operations.md) for artifact lifecycle and recovery. diff --git a/docs/config.md b/docs/config.md index 1b42609..46b721e 100644 --- a/docs/config.md +++ b/docs/config.md @@ -135,24 +135,14 @@ Hourly forecast data is required for generated reports. Supported optional source keys are `observations`, `current`, `narrative`, `alerts`, `discussion`, `weather_story`, and `spc_convective_outlooks`. -### `scriptorium` - -| Field | Default | Rules | -| --- | --- | --- | -| `binary` | `scriptorium` | Required executable name or path. | -| `config_path` | empty | Optional Scriptorium configuration path. | -| `profile` | empty | Optional Scriptorium profile. | -| `timeout` | `2m` | Must be greater than zero. | -| `extra_args` | empty | Optional extra arguments passed to Scriptorium commands. | - ### `promptkit` Promptkit configuration selects the executor and prompt/profile checks for -every `generate` command. Scriptorium settings remain in use by batch commands -while their compatibility workflow remains active. +every `generate` and `run` command. A top-level `scriptorium:` configuration +key is rejected with a migration error; it is not translated or ignored. Prompt debug capture has no YAML setting. Use `--llm-debug-dir PATH` on an -individual `generate` command when explicitly needed. +individual `generate` or `run` command when explicitly needed. | Field | Default | Rules | | --- | --- | --- | diff --git a/docs/development.md b/docs/development.md index cf152a3..bde29b5 100644 --- a/docs/development.md +++ b/docs/development.md @@ -46,7 +46,7 @@ present before introducing a new package or abstraction. | `internal/cli` | Command parsing, flags, help, output, and command wiring. | | `internal/app` | Generation, batches, collection coordination, notification, and inspection orchestration. | | `internal/config` | Configuration defaults, loading, precedence, secrets, and validation. | -| `internal/adapters` | Weather API, Promptkit, Scriptorium batch compatibility, and Distributor boundaries. | +| `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. | @@ -68,7 +68,7 @@ implemented subsystem behavior. 5. Run repository-wide validation before considering the work complete. Preserve actionable error context, keep secrets out of logs and fixtures, and -avoid validation that requires live Weather API, Scriptorium, or Distributor +avoid validation that requires live Weather API, Promptkit providers, or Distributor services. The architecture and testing policies own the detailed rules. ## Baseline Validation diff --git a/docs/integrations/promptkit.md b/docs/integrations/promptkit.md new file mode 100644 index 0000000..e413899 --- /dev/null +++ b/docs/integrations/promptkit.md @@ -0,0 +1,22 @@ +# Promptkit Integration + +Weatherreporter uses Promptkit for all generated-text reports. The four logical prompts are +`weather.daily_generated_text`, `weather.today_generated_text`, +`weather.tomorrow_generated_text`, and `weather.hourly_generated_text`, each at version +`1.0.0`. Their prompt assets and generated-text JSON Schemas are embedded by +`internal/promptassets`. + +Before collection, Weatherreporter inspects the exact prompt version, requires one required +`data_package` input with content type `application/yaml`, and requires the report's JSON +Schema output contract. It selects `promptkit.profile` when configured, otherwise the +prompt's declared default profile. Profiles that require a direct API key are unsupported; a +profile that reports `APIKeyEnv` requires a nonblank value in that environment variable. + +Execution receives the already-persisted YAML package, prepares it once, and returns structured +JSON that Weatherreporter validates before rendering its own Markdown template. Preparation and +execution receipts are project-owned, safe provenance records. Content-rich diagnostics are +opt-in through `--llm-debug-dir`; see [operations](../operations.md) for retention and permissions. + +Prompt/profile configuration is owned by the [configuration reference](../config.md). Adapter +construction and mapping are documented in the [Promptkit adapter internals](../internal/promptkit-adapter.md). +Durable metadata compatibility is described in [state internals](../internal/state.md). diff --git a/docs/integrations/scriptorium.md b/docs/integrations/scriptorium.md deleted file mode 100644 index a746022..0000000 --- a/docs/integrations/scriptorium.md +++ /dev/null @@ -1,90 +0,0 @@ -# Scriptorium Integration - -`weatherreporter` invokes the Scriptorium executable as a subprocess to -preflight prompt input and produce report artifacts. This is the limited CLI -contract Weatherreporter uses, not general Scriptorium documentation. - -## Invocation - -The configured `scriptorium.binary` is the executable name or path. When it is -empty, the adapter invokes `scriptorium`. Arguments are passed directly to the -process, without a shell. - -For every command, arguments occur in this order: - -1. The subcommand. -2. `--config ` when `scriptorium.config_path` is set. -3. `--profile ` when `scriptorium.profile` is set. -4. The command-specific arguments below. -5. Each configured `scriptorium.extra_args` item. - -The adapter uses these exact command shapes: - -```text -scriptorium render [--config ] [--profile ] \ - --prompt --input data_package= --format json \ - [ ...] - -scriptorium run [--config ] [--profile ] \ - --prompt --input data_package= --out \ - [ ...] -``` - -`render` is the preflight command. `run` writes a structured generated-text -artifact to the supplied `--out` path. It does not add `--format`, `--schema`, -`--schema-path`, or `--json-schema` flags. Prompt configuration selected by -`` controls that output. - -## Inputs and Outputs - -Weatherreporter always supplies exactly one prompt input: -`--input data_package=`. The path identifies the YAML data -package produced by the [prompt-input builder](../internal/prompt-input.md). -Its schema and the separate JSON module snapshots are internal artifacts, not -part of this CLI contract. - -The application supplies an already-managed output path to every `run` call. -For direct reports it is the Markdown artifact path. For generated-text -reports it is the raw JSON artifact path; subsequent validation and Markdown -rendering are owned by [generated-text processing](../internal/generatedtext.md). - -`render` has no output-path argument. Its JSON-formatted stdout remains -captured output: the adapter records it and does not parse it into a separate -CLI result type. Likewise, the adapter records `run` output metadata without -decoding the artifact written at `--out`. - -## Execution and Results - -`scriptorium.timeout`, when greater than zero, creates a timeout for each -subprocess invocation. Parent-context cancellation and that timeout stop the -command through the process context. - -Stdout and stderr are captured independently, each up to 1 MiB. Every returned -result records the complete argv as `command`, the captured `stdout` and -`stderr`, `exitCode`, and `stdoutTruncated` and `stderrTruncated` when a stream -was capped. Results from both forms of `run` also record `outputPath`, the -requested `--out` value. - -The [Scriptorium adapter](../internal/scriptorium-adapter.md) owns process -execution and result capture. [Application orchestration](../internal/app-orchestration.md) -owns when preflight output, report artifacts, and generated-text artifacts are -persisted. - -## Failure Behavior - -Before starting Scriptorium, the adapter requires a prompt ID and data-package -path for every command, plus an output path for `run`. Missing fields fail -without executing a subprocess. - -A nonzero process exit returns the captured result and an error that includes -the exit code and stderr. An output file written before such an exit does not -make the request successful. Failures to start the command, context -cancellation, and timeout return an error rather than a successful result. - -## Operational Notes - -- Extra arguments are argv items; they are not shell-interpreted. -- Prompt input, generated artifacts, stdout, and stderr can contain - operationally sensitive weather data. -- Provide API keys through the Scriptorium environment or its configuration, - not through Weatherreporter CLI arguments. diff --git a/docs/internal/app-orchestration.md b/docs/internal/app-orchestration.md index d129677..4e1ecde 100644 --- a/docs/internal/app-orchestration.md +++ b/docs/internal/app-orchestration.md @@ -1,126 +1,43 @@ # Application Orchestration Internals -`internal/app` composes top-level generation, batch, collection-save, and -inspection workflows after CLI parsing and configuration loading. It owns -workflow ordering, request composition, partial-result handling, and the -application-facing interfaces used for tests. +`internal/app` owns top-level generation, batch, collection, inspection, and +notification ordering after the CLI has parsed arguments and loaded configuration. -## Inputs And Outputs +## Generation -The package accepts generate, resolved-report, batch, explicit-collection, and -inspection requests. Generation and batch requests may supply collaborators for -tests; single-report generation uses a Promptkit executor, while batch requests -retain a renderer for their compatibility workflow. +`GenerateDetailed` resolves one of the four report definitions, initializes an +optional debug root, and inspects the exact Promptkit prompt/profile before it +collects weather or writes managed state. It then builds facts and modules, +saves the YAML data package, persists preparation metadata from the executor +callback, executes the prepared prompt, saves execution provenance and raw +output, validates generated text, renders Markdown, and optionally copies or +notifies from the managed report. -A report result contains the module snapshot, prompt package, prompt -provenance, generated-text artifacts, report and metadata -paths, prior snapshot, Recent Changes, and notification information. A batch -result contains aggregate counts, per-report outcomes, and an optional batch -notification. Inspection returns persisted values only. +Failure results retain all safe paths reached so far. Validation rejection +persists raw output and execution provenance but does not render a report. -Exact public command syntax, configuration fields, workspace layout, external -protocols, and report definitions belong in [the CLI reference](../cli.md), -[the configuration reference](../config.md), [operations](../operations.md), -and their focused integration and internal documents. +## Batches -`InspectPromptExecution` is a side-effect-free preflight helper for the prompt -workflow. It verifies the exact report prompt version, its required YAML input, -the generated-text JSON Schema contract, the selected profile, and any required -environment credential before collection or persistence begins. It returns only -safe project-owned identity and provenance values. +`RunBatchDetailed` constructs a single debug writer and uses the request's +single executor. Before collection it inspects Today, Tomorrow, and Daily for +morning, or Tomorrow and Daily for evening, deduplicating effective profile +inspection. It then collects once, plans eligible Daily dates, and calls the +same prompt-generation core sequentially for each planned report. Per-report +notification is suppressed; a failed report does not stop later reports. -## Single-Report Workflow +Batch notification is skipped when disabled or when any report failed. +Successful notification uses the completed managed report paths only. Batch +items retain preparation, execution, and optional debug paths when reached. -`GenerateDetailed` resolves the requested report using the configured registry -and current time, initializes any requested prompt-debug root, verifies the -exact Promptkit prompt and selected profile, and only then collects weather -data. Debug initialization or inspection failure produces no collection or -managed artifacts. +## Inspection And Boundaries -Single-report generation requires a non-nil normalized bundle and then performs this -ordered work: +Inspection loads persisted state only. It does not collect weather, invoke +Promptkit, or upload reports. The app coordinates project-owned contracts but +does not parse flags, load YAML, implement transport, construct provider SDKs, +or define report-period policy. -1. Select a state store, determine artifact destinations, and locate a prior - compatible snapshot. -2. Build report facts and deterministic module snapshots, then save the module - snapshot and calculate Recent Changes. -3. Serialize and save the prompt data package once, then use those exact bytes - for Promptkit execution. -4. Save preparation provenance and V2 metadata from the preparation callback - before provider execution. When requested, save preparation diagnostics in - the isolated debug store before the callback returns. Save execution - diagnostics immediately after a completed execution result, then persist raw - output and execution provenance before saving updated metadata. -5. Validate and save generated text, build and save a render context, and - render the managed Markdown template. -6. Optionally make an output copy, save final metadata, optionally notify - Distributor from the managed report path, and save metadata again when a - notification path is produced. +Focused checks: -Every single report looks up its catalog definition, saves raw Promptkit output, -preserves safe preparation and execution provenance separately, validates and -saves generated text, builds and saves a render context, then renders the -embedded Markdown template. Schema and template details remain in their -[generated-text](generatedtext.md) and [report-template](reporttemplate.md) -owners. - -Preparation and operational execution failures save classified receipts and -metadata before returning. A completed Promptkit validation rejection saves raw -output, an execution receipt, and metadata before returning. If later report -generation fails, the result retains every reached safe artifact path; output -copies and notification are skipped until rendering succeeds. - -The optional debug writer receives sensitive content only when explicitly -enabled. Its path is added to the report result only after a debug artifact is -successfully written; it is never copied into normal state records. - -## Batch And Inspection Workflows - -`RunBatchDetailed` collects once, asks the report registry to plan the batch -from that collection, and invokes its isolated Scriptorium compatibility helper -independently for every planned report using the same collection and state store. Per-report -notification is suppressed. A failed report is recorded and does not prevent -later planned reports from running. - -After report generation, the batch notifier is considered once. It is omitted -when Distributor or batch notification is disabled, skipped when any report -failed, and otherwise receives one multi-file request. A batch notification -failure increments the aggregate failure count but does not rewrite successful -report items. Notification identities, path mappings, polling, and redaction -are owned by the [Distributor adapter](distributor-adapter.md). - -Inspection methods create a state store and load existing report records, -metadata, module snapshots, prompt packages, prior snapshots, or source -provenance. They neither collect data nor invoke Scriptorium or Distributor. - -## Boundaries And Failure Propagation - -The app layer does not parse flags, load configuration files, implement Weather -API transport, invoke provider SDKs, or define report registry policy. It -coordinates the relevant collaborators and preserves their error context. - -- Prompt inspection failure stops a single report before collection or durable - writes. Collection failure stops a single report or batch before planning. -- State, fact, module, prompt-input, preparation, or execution failures stop - that report before later report generation. -- A terminal Distributor failure is returned with the saved notification - information when available. -- Batch failures are represented per report and through aggregate batch status. -- Persisted artifact paths are carried in results so callers can inspect work - completed before a later failure. - -## Tests And Invariants - -Focused tests are in `internal/app/app_test.go` and -`internal/app/batch_plan_test.go`, with collection coverage in -`internal/collect/collect_test.go`. - -- Production workflows collect through `internal/collect`. -- A report uses one explicit normalized collection throughout its generation. -- Prompt preparation provenance and metadata are persisted before provider - execution. -- Recent Changes compare structured module snapshots. -- Reports render from a validated typed context, never directly from a raw - prompt package. -- Only managed Markdown reports are notification sources; output copies are - never uploaded. +```sh +go test ./internal/app ./internal/collect +``` diff --git a/docs/internal/briefing.md b/docs/internal/briefing.md index 650ffef..d1573c2 100644 --- a/docs/internal/briefing.md +++ b/docs/internal/briefing.md @@ -4,7 +4,7 @@ collected facts, and derived facts. It owns the module registry, including module support, fact requirements, option types, missing-data policy, builders, and prompt-export hooks. It does not collect data, derive periods, write a -snapshot, construct YAML, invoke Scriptorium, or render a report. +snapshot, construct YAML, invoke Promptkit, or render a report. ## Registry and construction diff --git a/docs/internal/cli.md b/docs/internal/cli.md index 26a5e3f..4f4d62b 100644 --- a/docs/internal/cli.md +++ b/docs/internal/cli.md @@ -1,74 +1,23 @@ # CLI Internals -`internal/cli` turns process arguments into application requests and translates -application results into terminal output. The user-facing command, flag, and -output contract belongs in the [CLI reference](../cli.md). +`internal/cli` parses terminal arguments, loads configuration, constructs app +requests, and translates app results to bounded JSON summaries. The user +contract belongs in the [CLI reference](../cli.md). -## Responsibilities +For each `generate` or `run` action, `Runner` constructs one project-owned +Promptkit executor after configuration loads. It passes the executor and any +`--llm-debug-dir` request into the app. `run` accepts the debug flag as well +as `generate`; the app, not the CLI, secures and initializes the debug root. -`Runner.Run` dispatches the top-level action or inspection request. For actions, -the package parses command-specific and common flags, loads configuration with -CLI overrides, obtains the current time, and constructs either an -`app.GenerateRequest` or an `app.BatchRequest`. It delegates generation and -batch execution to `internal/app`. +Summaries include identity, status, safe artifact paths, and notification +provenance. They intentionally exclude module values, YAML package bodies, raw +generated text, rendered prompts, schemas, endpoints, credentials, and full +Distributor payloads. A failed action with a partial result still emits its +safe summary before its error is returned. -`Runner` also owns a project-owned prompt-executor factory seam. Its production -factory maps `promptkit` configuration to the Promptkit adapter, while tests can -inject a factory without importing dependency types. Each `generate` request -constructs one executor after configuration loads and passes it to the app. +CLI code owns no report policy, weather collection, persistence, provider +execution, or notification policy. Focused checks: -All four `generate` commands also accept `--llm-debug-dir PATH`. The CLI passes -only this explicit request to the app; the app initializes the secure debug -root before prompt inspection. `run` commands do not accept the flag. - -For inspection, it loads configuration, builds the appropriate app inspection -request, and writes the returned value. Inspection is read-only; the inspected -artifact types and user invocation remain owned by the [CLI reference](../cli.md) -and [operations guide](../operations.md). - -## Result Translation - -Action results become CLI-safe JSON summaries in `result.go`. Generate summaries -carry report identity, status, relevant artifact paths, and notification -summary data. Batch summaries carry aggregate counts, per-report outcomes, and -the optional batch notification result. The translation deliberately excludes -full module snapshots, prompt packages, raw generated text, Scriptorium output, -complete Distributor payloads, and prompt-debug content. - -When an action returns both a result and an error, the CLI writes the failed -summary before returning that error. Parse, configuration-load, and other -failures that produce no application result return without a summary. - -`writeActionResult` writes action status information to stderr first, then JSON -to stdout. Batch execution supplies the status writer; single-report generation -does not emit routine stderr output. Quiet action requests suppress both normal -streams but still return errors. Inspection writes its JSON value to stdout and -does not accept quiet mode because stdout is the inspection result. - -## Boundaries - -The package owns argument parsing, request adaptation, help text, and terminal -presentation. It does not implement report selection, collection, state -persistence, external transport, subprocess execution, or notification policy. -Those concerns remain in [application orchestration](app-orchestration.md) and -their focused owners. - -## Failure Behavior - -- Invalid command names, flags, dates, and configuration fail before an app - request is executed. -- Application errors retain their application context; output helpers do not - hide or replace them. -- JSON-encoding errors are returned directly. -- A failed batch summary causes the CLI to return an aggregate batch error even - when the detailed batch call has already returned its result. - -## Tests And Invariants - -Focused tests are in `internal/cli/root_test.go`, `internal/cli/output_test.go`, -and `internal/cli/result_test.go`. - -- CLI summaries are stable, bounded views of app results. -- Routine batch status lines precede the batch JSON summary. -- A quiet action produces no successful or failure summary output. -- Inspection never invokes action-output helpers. +```sh +go test ./internal/cli +``` diff --git a/docs/internal/collect.md b/docs/internal/collect.md index ed6f29d..566d186 100644 --- a/docs/internal/collect.md +++ b/docs/internal/collect.md @@ -13,7 +13,7 @@ calls `FetchBundle`, and returns `Result{Bundle: *weatherdata.Bundle}`. The package wraps adapter construction failures as weather-collection setup errors and fetch failures as bundle-collection errors. It does not retry, -persist, select reports, derive facts, build modules, invoke Scriptorium, or +persist, select reports, derive facts, build modules, invoke Promptkit, or notify Distributor. ## Application Composition diff --git a/docs/internal/generatedtext.md b/docs/internal/generatedtext.md index 9cea375..cef876f 100644 --- a/docs/internal/generatedtext.md +++ b/docs/internal/generatedtext.md @@ -33,7 +33,7 @@ template iteration rather than maps. Optional source stanzas become nil or fallback context fields. Missing required stanzas, type-decoding failures, invalid metadata, or a generated-text type that does not match the chosen handler fail before template execution. Prompt -packages, raw Scriptorium output, state persistence, and template asset lookup +packages, raw Promptkit output, state persistence, and template asset lookup remain outside this package. ## Verification and invariants diff --git a/docs/internal/prompt-input.md b/docs/internal/prompt-input.md index 8ea8fae..67ed315 100644 --- a/docs/internal/prompt-input.md +++ b/docs/internal/prompt-input.md @@ -2,9 +2,9 @@ `internal/promptinput` converts report metadata, an ordered module snapshot, Recent Changes, and source warnings into the YAML `data_package` consumed by -Scriptorium. It owns this package's schema, grouping, serialization, loading, +Promptkit. It owns this package's schema, grouping, serialization, loading, and validation—not weather collection, module construction, path choice, or -subprocess execution. +provider execution. ## Package construction diff --git a/docs/internal/promptkit-adapter.md b/docs/internal/promptkit-adapter.md new file mode 100644 index 0000000..b237591 --- /dev/null +++ b/docs/internal/promptkit-adapter.md @@ -0,0 +1,24 @@ +# Promptkit Adapter Internals + +`internal/adapters/promptkit` maps Weatherreporter's project-owned executor contract to Promptkit. +The CLI maps `promptkit` configuration to a `PromptExecutorConfig` and constructs one executor +per action. Promptkit dependency types do not escape the adapter. + +The adapter exposes exact prompt and profile inspection plus prepared execution. It maps Promptkit +inspection values to project-owned prompt input, output-contract, profile, preparation, execution, +validation, and optional debug values. It classifies adapter failures without copying provider secrets +or unbounded response bodies into application errors or normal state. + +The app calls the executor's preparation callback before provider execution to persist safe preparation +provenance. Completed executions are then persisted as safe execution provenance and raw generated text +is validated by `internal/generatedtext`. The adapter does not write workspace state, render Markdown, +choose report definitions, or send Distributor notifications. + +Focused tests: + +```sh +go test ./internal/adapters/promptkit ./internal/cli ./internal/app +``` + +The public logical prompt/profile/schema contract is owned by the +[Promptkit integration guide](../integrations/promptkit.md). diff --git a/docs/internal/report-registry.md b/docs/internal/report-registry.md index a45aac5..1e8505e 100644 --- a/docs/internal/report-registry.md +++ b/docs/internal/report-registry.md @@ -53,7 +53,7 @@ are likewise consumed by state and orchestration rather than recomputed there. Unknown report IDs or batch names return errors. The registry never collects weather data, builds modules, parses CLI flags, writes state, executes -Scriptorium, or delivers a report. +Promptkit, or delivers a report. ## Verification and invariants diff --git a/docs/internal/reporttemplate.md b/docs/internal/reporttemplate.md index 8daa63b..11981ef 100644 --- a/docs/internal/reporttemplate.md +++ b/docs/internal/reporttemplate.md @@ -1,22 +1,21 @@ # Report Template Internals `internal/reporttemplate` embeds and renders the repository's native Markdown -templates and exposes their companion generated-text schemas. The current asset -IDs are `daily`, `today`, `tomorrow`, and `hourly`. The template files, partials, -and complete render-context field reference are maintained in +templates. The current template IDs are `daily`, `today`, `tomorrow`, and +`hourly`. The template files, partials, and complete render-context field +reference are maintained in [report templates](../templates.md). ## Assets and lookup -The package embeds top-level templates, shared partials, and JSON schemas from -its asset directories. `Template` and `Schema` return the requested embedded -asset and fail with the requested ID when it is unknown or unreadable. +The package embeds top-level templates and shared partials. `Template` returns +the requested embedded template and fails with the requested ID when it is +unknown or unreadable. -Generated-text catalog handlers obtain schema bytes and template source through -these APIs. Prompt source files are repository assets for prompt registration; -they are not reporttemplate lookup assets. Report definitions select IDs, while -[generated-text internals](generatedtext.md) verifies the supported -schema/template pairing. +Generated-text schemas and Promptkit definitions are owned by +`internal/promptassets`; report-template owns Markdown source only. Report +definitions select IDs, while [generated-text internals](generatedtext.md) +verifies the supported schema/template pairing. ## Rendering @@ -36,16 +35,17 @@ validation. This package does not collect weather data, build modules, validate generated text, construct contexts, resolve report definitions, write state, execute -Scriptorium, or upload reports. It produces Markdown bytes for application +Promptkit, or upload reports. It produces Markdown bytes for application orchestration to persist. -Focused tests cover asset lookup, schema availability, rendering, partial +Focused tests cover template lookup, rendering, partial behavior, missing keys, and malformed context: ```sh go test ./internal/reporttemplate ``` -Embedded assets stay as separate files, shared fragments stay under the partial -directory, and generated-text schemas describe prose slots rather than -deterministic weather facts. +Embedded templates stay as separate files and shared fragments stay under the +partial directory. Generated-text schemas are embedded separately by +`internal/promptassets` and describe prose slots rather than deterministic +weather facts. diff --git a/docs/internal/scriptorium-adapter.md b/docs/internal/scriptorium-adapter.md deleted file mode 100644 index e06b52d..0000000 --- a/docs/internal/scriptorium-adapter.md +++ /dev/null @@ -1,51 +0,0 @@ -# Scriptorium Adapter Internals - -`internal/adapters/scriptorium` translates Weatherreporter render requests to -Scriptorium process arguments and translates process results back to local -types. The external CLI and output contract belongs to the -[Scriptorium integration guide](../integrations/scriptorium.md); prompts, -template inputs, and report ownership remain outside this adapter. - -## Request-to-command translation - -`Runner` accepts a binary, config path, profile, timeout, extra arguments, and -an injectable command executor. Its defaults are the `scriptorium` binary and -the real `ExecRunner`. Optional configuration flags are placed before the -operation-specific arguments, and extra arguments are appended last. - -| Local operation | Required values | Translated arguments | -| --- | --- | --- | -| `Render` | prompt ID, data-package path | `render [--config …] [--profile …] --prompt --input data_package= --format json [extra …]` | -| `Run` | prompt ID, data-package path, output path | `run [--config …] [--profile …] --prompt --input data_package= --out [extra …]` | -| `StructuredRun` | prompt ID, data-package path, output path | Same translation as `Run` | - -Blank required values fail before a command starts. The adapter does not add -schema flags or interpret a prompt's payload; it only gives Scriptorium the -named `data_package` input. - -## Command execution and result translation - -`ExecRunner` uses `exec.CommandContext`, never a shell. A positive configured -timeout creates a child context. Standard output and standard error are -captured independently, each with a 1 MiB limit, and the executed command is -retained for diagnostics. - -`RenderResult`, `RunResult`, and `StructuredRunResult` expose the command, -captured output, truncation markers, and exit code. Run results also retain the -requested output path. Exit status zero is successful. A nonzero process exit -returns its result and an error, while a start failure, cancellation, or -deadline failure returns no result and the execution error. - -The adapter does not parse rendered JSON, validate a generated report, write -state, or upload a report. Those responsibilities sit with -[application orchestration](app-orchestration.md), [state internals](state.md), and the -relevant delivery adapter. - -## Verification - -Focused tests cover argument order, validation, bounded capture, timeout and -cancellation handling, and exit-status translation: - -```sh -go test ./internal/adapters/scriptorium -``` diff --git a/docs/internal/state.md b/docs/internal/state.md index 9068f53..3e85d05 100644 --- a/docs/internal/state.md +++ b/docs/internal/state.md @@ -1,112 +1,44 @@ # State Internals -The `internal/state` package owns filesystem-backed run state: safe path -derivation, metadata persistence, prior-report lookup, and read-only report -inspection. It does not decide which reports to generate or deliver. For the -operator-facing layout and retention procedures, see the -[operations guide](../operations.md). +`internal/state` owns safe workspace paths, atomic artifact writes, metadata, +prior-snapshot lookup, and read-only inspection. Operators should use the +[operations guide](../operations.md) for lifecycle and retention. -## Store construction and artifact paths +## Artifact Paths -`NewFilesystemStore` requires a workspace root and rejects absolute or -escaping values for every configured state directory. `Paths` then validates a -run ID and artifact group before deriving all paths from the report's valid -start date (`YYYY-MM-DD`). This keeps a run's artifacts together while making -the paths safe to use below the configured workspace. +For each run, paths are grouped by artifact group and valid start date: -| Artifact | Derived location | +| Artifact | Location | | --- | --- | | Module snapshot | `snapshots///modules..json` | | Metadata | `snapshots///metadata..json` | | Data package | `data-packages///data_package..yaml` | | Prompt preparation | `preflight///prompt_preparation..json` | | Prompt execution | `snapshots///prompt_execution..json` | -| Render preflight | `preflight///render..json` | -| Notification record | `notifications///distributor..json` | +| Raw generated text | `snapshots///generated_text_raw..json` | +| Validated generated text | `snapshots///generated_text..json` | +| Render context | `snapshots///render_context..json` | | Managed report | `reports///report..md` | -| Generated text | `snapshots///generated_text..json` | -| Generated-text source and result | `snapshots///generated_text_raw..json` and `generated_text_result..json` | -| Generated-text render context | `snapshots///render_context..json` | +| Notification | `notifications///distributor..json` | -The configured notification root separates notification artifacts from report -artifacts; single-report notification paths use the report's valid date. Report -producers create parent directories as needed and write the report body; state -is responsible for the surrounding paths and saved run artifacts. +Batch notification records are `notifications/batches///distributor..json`. -Batch Distributor notifications are derived separately as -`notifications/batches///distributor..json`. -Their date is calculated from the batch start in its configured location, and -the batch identity and run ID receive the same path-segment validation as -single-report artifact identifiers. +## Metadata And Debug Storage -## Metadata and durable writes +New metadata is `weatherreporter.metadata.v2` and gains preparation and +execution paths only after those artifacts are saved. Legacy V1 records remain +readable; their historic preflight and generated-text-result fields are mapped +to the corresponding preparation and execution views during inspection. New +runs never write V1 records. -`Metadata` is the durable inventory for a run. It records its schema version, -run identity, generated and valid timestamps, artifact group, source content -and provenance, and the module snapshot, data-package, prompt preparation, -prompt execution, report, generated-artifact, and notification locations when -present. New prompt records use `weatherreporter.metadata.v2`; historic -`weatherreporter.metadata.v1` records remain readable and retain their legacy -JSON field names when inspected. +`PromptDebugWriter` is separate from workspace state. An empty root disables +it. An enabled absolute root is checked for safe directories and symlinks, then +stores `preparation.json` and `execution.json` beneath +`////`. Directories are `0700`; files are +atomic `0600`. Normal state discovery does not read this root. -`BuildMetadataFromBriefingMetadata` establishes legacy common fields, while -`BuildPromptMetadataFromBriefingMetadata` establishes the V2 record. The -application adds locations only after the corresponding artifacts are -produced. `SaveMetadata` requires the run ID, module snapshot, data package, -metadata path, and the matching preparation reference for its schema. The -package also saves module snapshots, data packages, prompt preparation and -execution records, legacy preflight records, generated-text artifacts, render -contexts, and notifications. JSON writes use atomic replacement, so readers do -not observe a partially written state file. - -## Explicit prompt debug storage - -`PromptDebugWriter` is a separate, opt-in boundary for content-rich prompt -diagnostics. It is constructed with an explicit absolute operator root, rather -than a workspace-derived path. A blank root produces a disabled writer that -does not access the filesystem. - -Enabled debug captures are grouped as -`////` and contain `preparation.json` and -`execution.json`. The writer rejects symlinks, unsafe path segments, path -escape, and non-directory roots; it creates its directories with `0700` and -writes files atomically with `0600`. Normal state discovery and inspection do -not read this root. Its wire records map only approved project-owned fields; -credentials and dependency objects are not persisted. - -The data package itself follows the shared -[prompt-input contract](prompt-input.md). Report text, templates, and external -delivery payloads remain owned by their respective packages and integration -references. - -## Prior reports and inspection - -`FindPriorSnapshot` searches metadata rather than guessing from filenames. It -only considers an earlier compatible report in the same artifact group and -supports the comparison strategies defined by the report request: - -- `same_valid_date` finds an earlier generated report for the same valid day. - -The newest eligible metadata record wins; the current run is excluded. -Unreadable or malformed candidate metadata is ignored so a damaged historical -record does not block a new run. - -`ListReports` walks saved metadata, returns results ordered newest-first by -generation time, and treats a missing snapshots directory as an empty history. -`LoadMetadataByRunID` builds on that inspection path. These APIs are read-only; -repairing or pruning stored state is an operational concern. - -## Boundaries and verification - -The package rejects unsafe path components and incomplete metadata before -writing. Callers must provide a valid report request, artifact group, and -store configuration. Its focused tests cover path derivation, atomic -persistence, metadata validation, comparison eligibility, and report listing: +Focused checks: ```sh go test ./internal/state ``` - -See [application orchestration](app-orchestration.md) for the order in which -these artifacts are created and [report templates](../templates.md) for the -user-facing report contract. diff --git a/docs/operations.md b/docs/operations.md index 857c77c..8a3ce29 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -44,10 +44,10 @@ continue. Run a scheduled batch with the same configured collection: ```sh -weatherreporter run morning --out-dir ./reports +weatherreporter run morning --out-dir ./reports --llm-debug-dir /var/tmp/weatherreporter-debug ``` -Each batch collects once before it plans reports. Morning runs Today, Tomorrow, +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 @@ -121,7 +121,7 @@ redacted errors; they do not contain tokens. ## Inspecting Stored Runs Inspection is read-only: it neither collects weather data nor invokes -Scriptorium or Distributor. Start by finding a RunID: +Promptkit or Distributor. Start by finding a RunID: ```sh weatherreporter inspect reports --limit 10 @@ -140,6 +140,12 @@ weatherreporter inspect metadata RUN_ID 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 @@ -163,7 +169,7 @@ first response; retain it until the failure is understood. ## Operational Caveats -- Workspace files, generated reports, and Scriptorium stderr can contain +- 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 diff --git a/docs/policy/architecture.md b/docs/policy/architecture.md index a481885..849f9ec 100644 --- a/docs/policy/architecture.md +++ b/docs/policy/architecture.md @@ -2,213 +2,72 @@ ## Purpose -This policy defines Weatherreporter's system shape, normative ownership, -dependency direction, architectural invariants, safety properties, and -non-goals. Developers and coding agents should use it to preserve the -application's boundaries as the implementation evolves. - -The [development guide](../development.md) owns the current package inventory -and contributor workflow. Focused documents under `docs/internal/` own -implemented subsystem mechanics. This policy owns the rules those packages and -mechanics must preserve. +This policy defines Weatherreporter's system shape, ownership, dependency direction, +and safety invariants. The [development guide](../development.md) owns the +package inventory; focused documents in `docs/internal/` own implementation detail. ## System Shape -Weatherreporter is a deterministic weather briefing and report-preparation CLI. -It consumes normalized weather data, derives report facts and module snapshots, -builds curated prompt packages, compares structured snapshots with prior runs, -and invokes Scriptorium either to produce managed Markdown directly or to -produce bounded generated-text prose for repository-owned templates. It -persists inspectable artifacts and can upload completed reports through -Distributor. +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. -The application is intentionally a small, explicit, dependency-light Go -program. Add abstraction only when it protects a real boundary, makes an -important invariant testable, or supports an implemented extension point. +The supported report products are Daily, Today, Tomorrow, and Hourly. A batch +collects once, validates its complete candidate prompt/profile set before +collection, then executes planned reports sequentially with one executor. It +continues after independent report failures and sends a batch notification only +after every planned report succeeds. -The primary flow is: +## Ownership And Boundaries -1. CLI parsing and configuration resolution; -2. report or batch resolution; -3. normalized weather collection; -4. deterministic fact derivation and module construction; -5. structured prior-snapshot comparison; -6. curated prompt input and report-mode-specific Scriptorium processing; -7. generated-text validation when applicable, managed Markdown production, - and metadata persistence; and -8. optional notification using managed report artifacts. +- `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. +- 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. -Inspection is a separate read-only flow over persisted state. It must not -collect weather data, invoke Scriptorium, or upload reports. +Dependency-specific Promptkit types remain inside its adapter. The application +does not parse flags, construct provider clients, or render provider output +directly. -## Ownership And Dependency Direction +## Prompt Execution Invariants -### Entry Point And CLI +- Prompts receive curated module packages, never unbounded raw weather payloads. +- Every execution inspects 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. +- 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. -The binary entry point should do no business work beyond constructing and -running the CLI. CLI code owns commands, arguments, flags, help, output -formatting, and conversion into application requests. +## State, Notification, And Testing Invariants -CLI packages must not own meteorological decisions, report composition, -artifact layout, Recent Changes comparison, external transport, or subprocess -construction. - -### Configuration - -Configuration loading, built-in defaults, overrides, secret loading, and -validation belong to `internal/config`. Operational values shared across -packages must be explicit configuration or constants owned by the responsible -package, not hidden in CLI or adapter code. - -The exact configuration contract belongs in the -[configuration reference](../config.md). Other architecture documents should -state ownership and safety rules rather than repeat fields, defaults, or -precedence. - -### Application Orchestration - -`internal/app` owns top-level use cases and workflow order. It composes report -resolution, collection, domain transformations, state, rendering, and optional -notification through narrow project-owned contracts. - -The application layer may coordinate components and convert between their -contracts. It must not absorb CLI parsing, HTTP transport, subprocess argument -construction, filesystem layout, weather derivation algorithms, template -execution, or adapter-specific dependency types. - -### Domain And Report Logic - -Meteorological selection, forecast-period resolution, daypart grouping, -threshold detection, fact derivation, report composition, module construction, -generated-text validation, and Recent Changes comparison belong in deterministic -Go domain packages. - -Domain packages must not depend on CLI parsing, process execution, remote -transport, or concrete external-library types. Given the same normalized -inputs, configuration, valid period, prior snapshot, and clock, domain behavior -should be reproducible. - -Report selection must go through the report registry or an equivalent -centralized mechanism. A report definition owns its identity, prompt and -rendering mode, valid-period resolver, module composition, comparison strategy, -artifact grouping, and output naming. Do not scatter report-ID conditionals -through CLI, orchestration, or adapters. - -### External Adapters - -External integrations use adapter boundaries under `internal/adapters`. -Adapters own transport and protocol mechanics; application and domain packages -own decisions. - -- The Weather API adapter owns HTTP request construction, timeouts, retries, - response-envelope handling, decoding, and endpoint compatibility. -- The Scriptorium adapter owns argument construction, context-aware subprocess - execution, stdout and stderr capture, exit interpretation, and result - decoding. It must avoid shell interpolation. -- The Distributor adapter owns dependency-specific bundle and upload types, - client construction, request execution, status handling, and redaction. - -External dependency types must not leak beyond the adapter that integrates -them. Adapters should expose narrow project-owned inputs and outputs so an -integration can be tested or replaced without changing domain logic. - -### State And Embedded Assets - -`internal/state` owns managed workspace paths, durable metadata, atomic -artifact persistence, prior lookup, and inspection reads. Other packages should -request state operations rather than reconstruct managed paths independently. - -Schemas, prompts, Markdown templates, and partials should live as separate -repository assets and be embedded by the package that owns their execution or -lookup. Keep weather derivation and path construction out of templates. - -## Architectural Invariants - -### Weather Truth And Generated Text - -- Normalized source data and deterministic Go derivation are authoritative for - weather facts. -- LLM prompts receive curated module-based packages rather than raw, - unbounded source payloads. -- Generated text is limited to defined prose slots, validated before use, and - rendered through typed or otherwise explicit contexts. -- Repository-owned templates arrange validated prose and deterministic facts; - they do not perform meteorological derivation. - -### Reports And Comparison - -- Report behavior is resolved through centralized definitions. -- Recent Changes is computed from structured module snapshots, never by - comparing rendered Markdown. -- Batch workflows collect normalized weather data once and reuse that - collection for planning and report generation. -- Report metadata links identity, generation time, valid period, source - provenance, and the managed artifacts produced for the run. - -### Managed State And Notification - -- Durable structured writes are atomic where practical. -- Managed paths remain beneath the configured workspace root. -- Operations that delete, move, overwrite, or copy files use narrow, explicit - paths; destructive cleanup is opt-in. -- Intermediate artifacts reached before a later failure remain inspectable - where practical. -- Distributor uploads use managed Markdown reports, never optional output - copies or broad workspace scans. -- Notification occurs only after the managed report and required metadata have - been successfully produced. - -### Security, Errors, And Cancellation - -- Secrets must not appear in logs, errors, persisted artifacts, examples, or - user-facing output. -- Errors preserve actionable operation, report, RunID, path, endpoint, or - subprocess context without exposing secrets or unnecessarily large payloads. -- External calls, subprocesses, storage operations, and multi-step workflows - accept or propagate `context.Context` where cancellation or timeout is - meaningful. -- Adapter failures preserve useful status, stderr, or response context at the - boundary and are translated into project-owned errors before crossing into - unrelated packages. - -## Dependency Policy - -Prefer the Go standard library. Add an external dependency only when it -materially improves correctness, security, interoperability, or -maintainability. A dependency used for a small convenience does not justify its -lifetime upgrade and compatibility cost. - -Keep dependency-specific types inside the package that intentionally adopts -the dependency. The application should remain understandable and testable -without requiring framework-wide abstractions or live external services. - -## Verification And Documentation - -Core behavior must be testable without live Weather API, Scriptorium, or -Distributor services. The [testing policy](testing.md) owns test philosophy, -sufficiency, boundaries, and test-double guidance. - -Documentation must follow the -[documentation policy](documentation.md). Update the canonical user, -operator, integration, internal, and example documentation in the same change -as the behavior it describes. Future or proposed behavior belongs under -`docs/roadmap/`; significant durable decisions may be recorded as ADRs. +- 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. +- Default tests are deterministic, offline, and use Promptkit/provider fakes + rather than live provider calls. See the [testing policy](testing.md). ## Non-Goals -Weatherreporter is not: - -- a source weather-data ingestion or normalization service; -- a general-purpose LLM orchestration framework; -- an application in which an LLM selects authoritative weather facts or report - policy; -- a plugin framework with dynamically discovered report or module behavior; -- an HTTP service or multi-user distributed job system; -- a replacement for Scriptorium or Distributor protocol ownership; or -- a system that hides operational state exclusively inside opaque logs or - remote services. - -New requirements may justify revisiting a non-goal. A change that alters system -shape, dependency direction, a safety property, or another architectural -invariant should be recorded deliberately in this policy or an ADR rather than -introduced implicitly. +Weatherreporter is not a weather-data ingestion service, general LLM +orchestration framework, plugin platform, HTTP service, multi-user job system, +or a replacement for Promptkit or Distributor. diff --git a/docs/policy/documentation.md b/docs/policy/documentation.md index 809ff58..429b968 100644 --- a/docs/policy/documentation.md +++ b/docs/policy/documentation.md @@ -87,7 +87,7 @@ mechanisms, not secret values. | Operations | `docs/operations.md` | Normal workflows, physical workspace layout, artifacts and metadata, inspection, notification behavior, recovery, cleanup, permissions, and operational caveats. | Complete CLI syntax, configuration field definitions, logical external contracts, and implementation mechanics. | | Troubleshooting | `docs/troubleshooting.md` | Recurring symptoms, likely causes, diagnostic steps, safe fixes, and links to normal-operation references. | Complete command and configuration references, routine operating procedures, and implementation detail. | | 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, Scriptorium, 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. | +| 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. | | Architectural decision history | `docs/adr/`, when repository-local decisions require records | Significant decisions, context, alternatives, rationale, consequences, and supersession history. | Current behavior reference, implementation status, and task sequencing. | | Temporary feature roadmaps | `docs/roadmap/`, while planned work needs coordination | Proposed, accepted, deferred, or rejected work; sequencing; gates; implementation status; and task breakdowns. | Implemented behavior reference and durable decision rationale. | diff --git a/docs/policy/testing.md b/docs/policy/testing.md index 11bdd7d..67d1916 100644 --- a/docs/policy/testing.md +++ b/docs/policy/testing.md @@ -54,8 +54,8 @@ Use a classical or Detroit-style approach: - Test exact collaborator interactions only when the interaction itself is a requirement. -Weatherreporter's important seams include clocks, subprocesses, HTTP services, -Distributor uploads, filesystem roots, environment-backed secrets, and any +Weatherreporter's important seams include clocks, Promptkit executors, HTTP +services, Distributor uploads, filesystem roots, environment-backed secrets, and any future source of randomness or nondeterminism. ## Execution Requirements @@ -73,7 +73,7 @@ package command while iterating and `go test -race ./...` when the risk crosses package boundaries. Tests in the default suite must be deterministic, offline, and independent of -real credentials. They must not invoke live Weather API, Scriptorium, or +real credentials. They must not invoke live Weather API, Promptkit providers, or Distributor services or depend on other mutable external infrastructure. Tests that require live infrastructure must be explicitly opt-in and clearly separated from the default suite. @@ -198,7 +198,7 @@ Each behavior should have a clear test owner: - CLI parser tests own arguments, flags, and command construction. - Config tests own loading, precedence, defaults, secrets, and validation. - Domain tests own weather transformations and invariants. -- Adapter tests own HTTP, subprocess, and upload boundaries. +- 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. @@ -220,7 +220,7 @@ observation: 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 Scriptorium, or +metadata before notification, 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. @@ -232,7 +232,7 @@ Use: - `t.TempDir()` for real filesystem behavior; - `httptest.Server` for realistic Weather API interactions; - test-controlled clocks for periods and RunIDs; -- fake command runners for Scriptorium behavior; +- fake Promptkit executors or provider clients for Promptkit behavior; - fake upload clients for Distributor behavior; - fuzz tests when parsers, normalization, or path handling have a broad and consequential input space; diff --git a/docs/roadmap/scriptorium/prompts/common/data_package.user.md b/docs/roadmap/scriptorium/prompts/common/data_package.user.md deleted file mode 100644 index 5aac56c..0000000 --- a/docs/roadmap/scriptorium/prompts/common/data_package.user.md +++ /dev/null @@ -1,107 +0,0 @@ -Your task is to generate a local weather forecast analysis from the following YAML data package, which is prepared by the weatherreporter application. - -Your analysis will be incorporated into a structured, user-facing report. The report may be for today, tomorrow, or a future date. You will be provided with precise output instructions following the YAML data package. - -# SOURCE ROLES AND WEIGHTING - -Use `report` and `briefing.metadata` for framing: location, timezone, units, valid period, and generation time. Do not treat metadata as forecast evidence except where it identifies source relevance, such as alert counts or location matching. - -For weather interpretation, think in four source layers, in this order: - -## 1. Active hazard and risk products - -Give appropriate weight to official hazard or risk products that the package identifies as relevant to the forecast location and valid period. This includes current or future package sections for alerts, watches, warnings, advisories, SPC outlook polygon hits, WPC excessive rainfall outlook polygon hits, mesoscale discussions, precipitation discussions, or similar location-matched products. - -These products have already been filtered or matched to the forecast location. Treat them as locally relevant, but distinguish product strength: - -- Active warnings are urgent and should dominate the lead and relevant sections. -- Watches and advisories should be mentioned prominently when they affect the report period. -- Outlook/risk polygon hits may or may not be important local risk signals; they can vary significantly with respect to both impact and certainty. Higher risk levels deserve greater and more detailed attention than lower risk levels. Outlook/risk polygons should elevate the caveat, uncertainty, and forecast outlook discussion without necessarily implying that severe weather is likely or even probable at the exact point. -- Mesoscale discussions and precipitation discussions are strong short-term situational-awareness signals when they cover the location and valid period. - -For the current schema, use `briefing.applicable_risk_products.alert_digest` and `briefing.metadata.alerts` to determine whether relevant local alerts exist. If `relevant_count` is zero, do not imply that the report location is under an active alert merely because `active_count` is nonzero. - -## 2. Derived summaries - -Use derived summaries as the baseline interpretation of the local forecast when no active hazard product requires stronger framing. - -For the current schema: - -- Use `briefing.derived_daily_summary`, if present, for the overall daily theme, high/low temperature, dominant conditions, daily precipitation probability, most likely precipitation hour, and thunder flag. -- Use `briefing.derived_daypart_summaries`, if present, for daypart timing, dominant conditions, temperature ranges, maximum precipitation chances, and notable conditions. -- Use `briefing.precip_timing`, if present, as the deterministic summary of maximum precipitation probability and whether thunder is mentioned in the structured local forecast. -- Use `briefing.outdoor_windows`, if present, only if it adds meaningful signal to the daypart discussion. Do not turn the report into outdoor-planning advice. - -## 3. Narrative products - -Use `briefing.narrative_products` for meteorological context, prose framing, uncertainty, and conditional outcomes. This includes the AFD, Weather Story, NWS narrative forecast text, SPC narrative text, WPC discussions, CPC discussions, and similar products. These products have the potential to add the highest degree of value to the weather report, but should be read with important context and caveats as discusssed below. - -For the current schema: - -- Use `briefing.narrative_products.narrative_forecast.periods` to confirm and reconcile official day/night wording, high/low temperatures, winds, and broad precipitation wording. -- Use `briefing.narrative_products.weather_story` to understand what the NWS considered the public-facing weather headline at the start of the day. Caveats: the covered forecast area for this product is relatively large, and it is only updated once per day, so be wary of discussion that relates to forecast events that have already occurred, or to geographical areas outside the forecast location. -- Use `briefing.narrative_products.area_forecast_discussion.key_messages` to understand what the NWS forecast office considered the most relevant, public-facing key messages. This product is updated somewhat more frequently than `briefing.narrative_products.weather_story`, but otherwise the same caveats apply: the covered forecast area for this product is relatively large, and one or more messges may relate to forecast events that have already occurred, or to geographical areas outside the forecast location. -- Use `briefing.narrative_products.area_forecast_discussion.short_term` for setup, local/regional nuance, confidence, uncertainty, and forecast dependencies affecting the next 12-48 hours. -- Use `briefing.narrative_products.area_forecast_discussion.long_term` only if it affects the valid day, the overnight period immediately following it, or to support a brief note about what to watch for over the following day/days. -- If `briefing.narrative_products.spc_convective_discussion.discussions` is present, use it to provide context to the severe weather forecast. Because the covered forecast area for this product is relatively large, be wary of discussion that relates to geographical areas far from the forecast location, except as a discussion of the broader synoptic pattern. Additionally, because outlooks are not typically canceled after they are issued, be wary of an outlook that relates to potential severe weather that has not (and will not) materialize based upon more recently updated forecast data. - -Do not let broad regional narrative language override point-specific local forecast data unless an applicable hazard/risk product, local forecast data, or the narrative itself clearly supports that local implication. - -## 4. Raw underlying data - -Use `briefing.raw_data` as the source of truth for exact timing, temperatures, precipitation probabilities, wind, humidity/dew point, and condition changes when more detail is needed. - -For the current schema, `briefing.raw_data.hourly_forecast.periods` is the most granular local forecast source. - -Use `briefing.raw_data.current_conditions` only as generation-time context. - -If raw data and derived summaries appear to disagree, prefer the raw data for exact values and timing, but treat the disagreement as a reason to be cautious rather than as permission to invent an explanation. - -# CONFLICT RESOLUTION - -When sources differ, ask: - -1. Which source is most local to the forecast point? -2. Which source is valid for the report period or near-term window? -3. Which source is most authoritative for the type of claim being made? -4. Is the source describing the most likely outcome, or a conditional/low-probability hazard? - -Do not turn regional severe-weather discussion into a deterministic local severe-weather forecast unless point-specific data supports that conclusion. Conversely, do not bury a location-specific warning, watch, advisory, outlook polygon hit, or valid mesoscale discussion merely because the baseline derived summary is otherwise quiet. - -# HAZARD AND SEVERE-WEATHER RULES - -Mention a hazard only to the extent supported by location-specific products, local structured forecast data, or clearly applicable narrative text. - -Preserve product strength and uncertainty. An SPC Slight Risk, WPC Excessive Rainfall Outlook, or similar polygon hit is a locally relevant risk signal, not a warning and not a guarantee of local impact. - -Preserve geography. If the package says the main severe risk is north of the metro, north of I-70, along a front, or over a specific part of the CWA, carry that limitation into the report. - -Preserve timing. Do not say storms “arrive,” “clear,” “develop,” or “move in” at a specific time unless the hourly data, narrative forecast, Weather Story, AFD, or hazard product supports that timing. - -# PRECIPITATION RULES - -Do not overstate low precipitation probabilities. - -Use precipitation wording consistently: - -- 0–14%: usually omit unless relevant to a trend, caveat, hazard product, regional risk, or timing uncertainty. -- 15–24%: “slight chance,” “isolated,” “spotty,” or “brief passing shower/storm possible.” -- 25–39%: “chance,” “scattered,” or “some showers/storms possible.” -- 40–59%: “good chance” or “showers/storms likely enough to plan around.” -- 60%+: “likely,” “wet,” or “unsettled,” if consistent with the narrative forecast. - -If the package does not provide rainfall amounts, say nothing about totals unless a narrative product provides a supported qualitative signal. Do not invent QPF. - -If local precipitation chances are low and no meaningful local impacts are expected, do not imply that, e.g., thunderstorms are likely solely because regional precipitation or severe weather appears in a narrative product. Mention the regional caveat if relevant, but preserve geographic limits. - -# STYLE RULES - -- Plainspoken, precise, and weather-literate. -- Compact, but not shallow. -- No generic public-safety filler. -- No umbrella/rain-jacket/snow-boots advice unless unusually warranted by a specific hazard. -- No commute or outdoor-plan boilerplate. -- No unsupported precision. -- No apologies for missing data. -- Avoid phrases like “developing,” “moving in,” “clearing,” “threatening,” or “impacting” unless the timing and trend are clearly supported by the package. -- Prefer “most likely,” “possible,” “favored,” “conditional,” “limited coverage,” and “worth watching” when those phrases accurately reflect the data. \ No newline at end of file diff --git a/docs/roadmap/scriptorium/prompts/common/system.md b/docs/roadmap/scriptorium/prompts/common/system.md deleted file mode 100644 index d34fbc2..0000000 --- a/docs/roadmap/scriptorium/prompts/common/system.md +++ /dev/null @@ -1,9 +0,0 @@ -You are WeatherReporter, a concise personal weather briefing writer. - -You generate local weather forecast analysis from structured data packages prepared by the weatherreporter application. - -Use only the provided data package as your source of truth. Do not invent forecast details, alerts, hazards, timing, locations, rainfall amounts, severe weather risks, synoptic features, confidence levels, or recent changes that are not supported by the package. - -The reader is intelligent and weather-literate, but not a professional meteorologist. If asked to provide narrative analysis or commentary, write in plain, precise, meteorologically informed language. Avoid hype, filler, generic safety advice, and TV-weather style. Provide polished prose that avoids highly technical meteorological jargon or shorthand. - -Do not mention that you are an AI model. diff --git a/docs/roadmap/scriptorium/prompts/daily/daily_generated_text.user.md b/docs/roadmap/scriptorium/prompts/daily/daily_generated_text.user.md deleted file mode 100644 index 0291eb8..0000000 --- a/docs/roadmap/scriptorium/prompts/daily/daily_generated_text.user.md +++ /dev/null @@ -1,63 +0,0 @@ -TASK: You are writing structured prose slots for a daily weather report. - -The calling application will render the final Markdown report. Your job is not to write the full report. Return only a JSON object matching the configured schema. - -Use only the supplied `data_package`. Do not invent weather details, times, hazards, probabilities, or impacts that are not supported by the data. - -The report focuses on the valid period in `report.valid_period`, which corresponds to an upcoming civil day for the configured location. - -Return these fields: - -- `summary`: required. 1-2 sentences summarizing the main weather story for the valid period. -- `forecast_discussion`: required. 3 paragraphs explaining the broader setup, trend, and/or forecast reasoning most relevant to the valid period. -- `precipitation_timing`: optional. Include only when the deterministic `precip_timing` module contains precipitation windows. - -Return JSON only. - -# summary - -The summary should typically consist of two sentences. - -If an active warning is relevant during the report period, lead with the hazard. Otherwise, the first sentence should state the most likely local weather outcome for the valid period, including the overall character of the weather and expected temperature/temperature range. - -The second sentence should state the most important active hazard, caveat, uncertainty, or alternate outcome, if one exists. If there is no meaningful caveat, the second sentence may be omitted. - -In the lead, distinguish the main weather outcome from the caveat. If showers and thunderstorms have different timing, state that difference rather than combining them as a single risk throughout the valid period. If the main caveat is a regional severe-weather or precipitation risk displaced from the report location, state that limitation clearly. - -Example style: - -- “Today is expected to be warm and dry, with mostly clear skies. There is a slight chance of isolated showers and thunderstorms developing from late afternoon into early evening.” - -# forecast_discussion - -Use narrative products to explain the “why” behind the local forecast when useful. Useful context may include: - -- synoptic pattern -- fronts or boundaries -- shortwaves, troughs, or ridges -- instability, moisture, shear, forcing, or capping -- regional placement of precipitation or severe-weather chances -- hazard types and timing windows -- confidence or uncertainty -- conditional outcomes -- relevant notes about the following day or days - -In most cases, the `forecast_discussion` should include three paragraphs: - -1. 2–4 sentences summarizing the relevant local/regional setup. -2. 2-4 sentences describing the main forecast uncertainty or conditional factor, if present. -3. 2-4 sentences about the next day or broader pattern if supported. - -# precipitation_timing - -Optional. Return only if precipitation is forecast. If present, provide 1 to 4 sentences to add practical context, including: - - - Whether the precipitation is associated with a moving frontal boundary, convective initiation, or wide stratiform rain (if this can be determined from the data package); - - The expected type, intensity, and duration of the precipitation; and - - Any caveats or uncertainty with respect to the onset, duration, or occurrance of the precipitation. - -# Narrative Source Selection - -As previously noted, use `briefing.derived_daily_summary`, `briefing.derived_daypart_summaries`, `briefing.narrative_products.narrative_forecast.periods`, and `briefing.raw_data.hourly_forecast.periods` as your primary reference sources for forecast. - -As previously noted, narrative sources can provide significant added value, but you must think carefully about whether information from the available narrative sources is relevant to the valid period. If the valid period relates to a civil day that is several days in the future, then products such as `briefing.narrative_products.weather_story`, `briefing.narrative_products.area_forecast_discussion.key_messages`, and `briefing.narrative_products.area_forecast_discussion.short_term` may have limited relevance. On the other hand, `briefing.narrative_products.area_forecast_discussion.long_term` may have relatively more relevance. diff --git a/docs/roadmap/scriptorium/prompts/daily/daily_generated_text.yml b/docs/roadmap/scriptorium/prompts/daily/daily_generated_text.yml deleted file mode 100644 index 8ff6f8a..0000000 --- a/docs/roadmap/scriptorium/prompts/daily/daily_generated_text.yml +++ /dev/null @@ -1,25 +0,0 @@ -id: weather.daily_generated_text -version: "1.0.0" -default_profile: local-heavy -#default_profile: gemini-3-flash-lite -description: Daily weather report analysis prompt. -inputs: - - name: data_package - required: true - content_type: application/json - description: Structured weather data package -messages: - - role: system - content_file: ../common/system.md - - role: user - content_file: ../common/data_package.user.md - - role: user - content: | - {{input "data_package"}} - - role: user - content_file: ./daily_generated_text.user.md -output: - format: json - validation_mode: json_schema - schema_path: pipeline-weather/daily/daily.generated_text.schema.json - repair_attempts: 2 \ No newline at end of file diff --git a/docs/roadmap/scriptorium/prompts/daily_report/daily_report.system.md b/docs/roadmap/scriptorium/prompts/daily_report/daily_report.system.md deleted file mode 100644 index afd65bb..0000000 --- a/docs/roadmap/scriptorium/prompts/daily_report/daily_report.system.md +++ /dev/null @@ -1,13 +0,0 @@ -You are WeatherReporter, a concise personal weather briefing writer. - -You generate local daily weather briefings from structured data packages prepared by the weatherreporter application. - -The reader is weather-literate and interested in meteorology. Do not write a generic public weather report. Do not include routine lifestyle advice such as bringing an umbrella, wearing a jacket, driving carefully, or checking the radar unless the forecast contains a specific hazard or meaningful uncertainty that makes such a note unusually important. - -Your job is to identify the most likely weather outcome, state meaningful caveats or uncertainty, summarize the daypart forecast, and explain the meteorological setup when useful. - -Use only the provided data package as your source of truth. Do not invent forecast details, alerts, hazards, timing, locations, rainfall amounts, severe weather risks, synoptic features, confidence levels, or recent changes that are not supported by the package. - -Write in plain, precise, meteorologically informed language. Avoid hype, filler, generic safety advice, and TV-weather style. Do not mention that you are an AI model. Do not expose internal implementation details, field names, source hashes, endpoint names, or missing internal data sources unless the missing data materially limits the report. - -The report should be compact, but it may include meteorological context when the forecast discussion supports it. \ No newline at end of file diff --git a/docs/roadmap/scriptorium/prompts/daily_report/daily_report.user.md b/docs/roadmap/scriptorium/prompts/daily_report/daily_report.user.md deleted file mode 100644 index 1bd0745..0000000 --- a/docs/roadmap/scriptorium/prompts/daily_report/daily_report.user.md +++ /dev/null @@ -1,234 +0,0 @@ -Generate a Daily Weather Report from the following weatherreporter YAML data package. - -The report may be for today, tomorrow, or a future date. Determine the correct framing from report, briefing.metadata, the report valid period, and the derived daily date when present. - -Use Markdown. - -# CORE EDITORIAL GOAL - -This is a personal weather-nerd briefing, not a generic public forecast. The report should answer: - -1. What is the most likely local weather outcome for the day? -2. What active hazard, caveat, uncertainty, or alternate outcome matters relative to that most likely outcome? -3. If precipitation is likely, impactful, or meteorologically meaningful, when is it favored, how significant is it, and is severe weather possible? -4. What should each daypart generally look and feel like? -5. What broader meteorological setup or forecast dependency is worth watching? - -# SOURCE ROLES AND WEIGHTING - -Use report and briefing.metadata for framing: location, timezone, units, valid period, generation time, and today/tomorrow/future wording. Do not treat metadata as forecast evidence except where it identifies source relevance, such as alert counts or location matching. - -For weather interpretation, think in four source layers, in this order: - -## 1. Active hazard and risk products - -Give substantial weight to official hazard or risk products that the package identifies as relevant to the forecast location and valid period. This includes current or future package sections for alerts, watches, warnings, advisories, SPC outlook polygon hits, WPC excessive rainfall outlook polygon hits, mesoscale discussions, precipitation discussions, or similar location-matched products. - -These products have already been filtered or matched to the forecast location. Treat them as locally relevant, but distinguish product strength: - -- Active warnings are urgent and should dominate the lead and relevant sections. -- Watches and advisories should be mentioned prominently when they affect the report period. -- Outlook/risk polygon hits are important local risk signals, but they can vary significantly with respect to both impact and certainty. Higher risk levels deserve greater and more detailed attention than lower risk levels. Outlook/risk polygons should elevate the caveat, uncertainty, and ## What to Watch discussion without necessarily implying that severe weather is certain at the exact point. -- Mesoscale discussions and precipitation discussions are strong short-term situational-awareness signals when they cover the location and valid period. - -For the current schema, use `briefing.applicable_risk_products.alert_digest` and `briefing.metadata.alerts` to determine whether relevant local alerts exist. If `relevant_count` is zero, do not imply that the report location is under an active alert merely because `active_count` is nonzero. - -## 2. Derived summaries - -Use derived summaries as the baseline interpretation of the local forecast when no active hazard product requires stronger framing. - -For the current schema: - -- Use briefing.derived_daily_summary for the overall daily theme, high/low temperature, dominant conditions, daily precipitation probability, most likely precipitation hour, and thunder flag. -- Use briefing.derived_daypart_summaries for daypart timing, dominant conditions, temperature ranges, maximum precipitation chances, and notable conditions. -- Use briefing.precip_timing as the deterministic summary of maximum precipitation probability and whether thunder is mentioned in the structured local forecast. -- Use briefing.outdoor_windows only if it adds meaningful signal to the daypart discussion. Do not turn the report into outdoor-planning advice. - -## 3. Narrative products - -Use `briefing.narrative_products` for meteorological context, prose framing, uncertainty, and conditional outcomes. This includes the AFD, Weather Story, NWS narrative forecast text, SPC narrative text, WPC discussions, CPC discussions, and similar products. - -For the current schema: - -- Use `briefing.narrative_products.narrative_forecast.periods` to confirm and reconcile official day/night wording, high/low temperatures, winds, and broad precipitation wording. -- Use `briefing.narrative_products.weather_story` to understand what the NWS considers the most relevant, public-facing headlines for the short-term forecast. Because the covered forecast area for this product is relatively large, be wary of discussion that relates to geographical areas outside the forecast location, and preserve spatial limits such as “north of I-70.” -- Use `briefing.narrative_products.area_forecast_discussion.key_messages` and `briefing.narrative_products.area_forecast_discussion.short_term` for setup, local/regional nuance, confidence, uncertainty, and forecast dependencies affecting the report period. -- Use `briefing.narrative_products.area_forecast_discussion.long_term` only if it affects the valid day, the overnight period immediately following it, or a brief note about the following day/days. -- If `briefing.narrative_products.spc_convective_discussion.discussions` is present, use it to understand and to provide context to the severe weather forecast. Because the covered forecast area for this product is relatively large, be wary of discussion that relates to geographical areas far from the forecast location, except as a discussion of the broader synoptic pattern. - -Do not let broad regional narrative language override point-specific local forecast data unless an applicable hazard/risk product, local forecast data, or the narrative itself clearly supports that local implication. - -## 4. Raw underlying data - -Use `briefing.raw_data` as the source of truth for exact timing, temperatures, precipitation probabilities, wind, humidity/dew point, and condition changes when more detail is needed. - -For the current schema, `briefing.raw_data.hourly_forecast.periods` is the most granular local forecast source. Use it to verify daypart summaries, refine timing, identify trends, and resolve ambiguity. - -Use `briefing.raw_data.current_conditions` only as generation-time context. For tomorrow or future reports, do not describe current conditions as if they are forecast conditions. - -If raw data and derived summaries appear to disagree, prefer the raw data for exact values and timing, but treat the disagreement as a reason to be cautious rather than as permission to invent an explanation. - -# CONFLICT RESOLUTION - -When sources differ, ask: - -1. Which source is most local to the forecast point? -2. Which source is valid for the report period or near-term window? -3. Which source is most authoritative for the type of claim being made? -4. Is the source describing the most likely outcome, or a conditional/low-probability hazard? - -Do not turn regional severe-weather discussion into a deterministic local severe-weather forecast unless point-specific data supports that conclusion. Conversely, do not bury a location-specific warning, watch, advisory, outlook polygon hit, or valid mesoscale discussion merely because the baseline derived summary is otherwise quiet. - -# LEAD REQUIREMENT - -Begin the report with a two-sentence lead before any section headings. - -If an active warning is relevant during the report period, lead with the hazard. Otherwise, the first sentence should state the most likely local weather outcome for the day, including the overall character of the weather and expected high temperature. - -The second sentence should state the most important active hazard, caveat, uncertainty, or alternate outcome, if one exists. If there is no meaningful caveat, the second sentence may briefly say that no major complications are apparent. - -In the lead, distinguish the main weather outcome from the caveat. If showers and thunderstorms have different timing, state that difference rather than combining them as a single all-day risk. If the main caveat is a regional severe-weather or precipitation risk displaced from the report location, state that limitation clearly. - -Example style: - -- “Tomorrow is expected to be warm, mostly cloudy, and mostly dry, with a high near 72. There is a slight chance of isolated showers and thunderstorms from late afternoon into early evening.” - -Do not open with generic planning advice. - -# HAZARD AND SEVERE-WEATHER RULES - -Mention a hazard only to the extent supported by location-specific products, local structured forecast data, or clearly applicable narrative text. - -Preserve product strength and uncertainty. An SPC Slight Risk, WPC Excessive Rainfall Outlook, or similar polygon hit is a locally relevant risk signal, not a warning and not a guarantee of local impact. - -Preserve geography. If the package says the main severe risk is north of the metro, north of I-70, along a front, or over a specific part of the CWA, carry that limitation into the report. - -Preserve timing. Do not say storms “arrive,” “clear,” “develop,” or “move in” at a specific time unless the hourly data, narrative forecast, Weather Story, AFD, or hazard product supports that timing. - -# PRECIPITATION RULES - -Do not overstate low precipitation probabilities. - -Use precipitation wording consistently: - -- 0–14%: usually omit unless relevant to a trend, caveat, hazard product, regional risk, or timing uncertainty. -- 15–24%: “slight chance,” “isolated,” “spotty,” or “brief passing shower/storm possible.” -- 25–39%: “chance,” “scattered,” or “some showers/storms possible.” -- 40–59%: “good chance” or “showers/storms likely enough to plan around.” -- 60%+: “likely,” “wet,” or “unsettled,” if consistent with the narrative forecast. - -Include ## Precipitation Details only when precipitation is likely, potentially impactful, or meteorologically interesting. In that section, address as many of the following as the data supports: - -- likely or favored start/end timing -- most likely precipitation window -- expected intensity -- expected rainfall amount -- thunderstorm potential -- severe-weather potential -- uncertainty in timing, coverage, or placement - -If the package does not provide rainfall amounts, say nothing about totals unless a narrative product provides a supported qualitative signal. Do not invent QPF. - -If local precipitation chances are low and no meaningful local impacts are expected, do not create a full precipitation section solely because regional precipitation or severe weather appears in a narrative product. Mention the regional caveat in the lead or ## What to Watch instead, preserving geographic limits. - -# DAYPART RULES - -Use dayparts from briefing.derived_daypart_summaries. If a daypart is present but incomplete, use raw hourly data and narrative forecast periods to fill in only what is supported. Only include dayparts present in the package. - -In ## Daypart Forecast, each bullet should usually follow this pattern: - -- **Daypart:** [Sky/general condition] with [temperature trend or approximate temperature]. [Precipitation/storm/hazard sentence only if relevant.] [Wind sentence only if meaningful.] - -Always include the expected sky or general condition when supported, such as mostly cloudy, partly cloudy, sunny, overcast, rainy, snowy, foggy, or stormy. - -Prefer natural temperature phrasing: - -- “temperatures around 82” -- “temperatures rising from the upper 60s into the low 70s” -- “temperatures near 80” -- “cooling from the low 80s into the low 70s” -- “holding in the upper 60s” -- “peaking near 83 late in the day” - -For quiet or mostly dry dayparts, keep the bullet to one sentence. For dayparts with meaningful precipitation, thunder, snow, ice, fog, high wind, heat, or other weather impacts, add a second sentence with timing and caveat details. - -Keep sky/general condition separate from precipitation probability. Do not write only “slight chance of showers” when the broader condition is “mostly cloudy with a slight chance of showers.” - -When precipitation or hazards are likely during only part of a daypart, describe that timing first, then describe the sky/temperature trend. Do not lead with a benign sky condition if showers, storms, snow, ice, fog, or other impacts are likely during that same daypart. - -Avoid “throughout the day” unless the same weather risk is meaningfully present across most dayparts. - -# METEOROLOGICAL CONTEXT RULES - -Use narrative products to explain the “why” behind the local forecast when useful. - -Useful context may include: - -- synoptic pattern -- fronts or boundaries -- shortwaves, troughs, or ridges -- instability, moisture, shear, forcing, or capping -- regional placement of precipitation or severe-weather chances -- hazard types and timing windows -- confidence or uncertainty -- conditional outcomes -- relevant notes about the following day or days - -Do not simply quote or summarize narrative products at length. Translate them into concise, plainspoken, weather-literate context. - -# OUTPUT FORMAT - -Use this structure: - -# [Today’s/Tomorrow’s/DOW's] Weather — [Location Name] - -[Valid date] - -[Two-sentence lead.] - -## Daypart Forecast - -- Morning: ... -- Midday: ... -- Afternoon: ... -- Evening: ... -- Overnight: ... - -Only include dayparts present in the package. Use natural language timing where helpful. - -## Precipitation Details - -Include this section only if: - -- local precipitation probability reaches at least 30% during the valid period; -- thunder is mentioned in the structured local forecast and the timing/coverage is meteorologically interesting; -- a relevant hazard/risk product discusses flooding, severe weather, winter weather, high wind, or another meaningful precipitation-related hazard; -- narrative products discuss intensity, rainfall rates, flooding, severe potential, or meaningful uncertainty that plausibly affects the report location or is important regional context; -- recent changes materially affect precipitation timing, coverage, or intensity. - -## Recent Changes - -Include this section only if recent_changes.items contains meaningful changes. Summarize changes in plain English. Do not fabricate changes. - -## What to Watch - -Include meteorological context, uncertainty, conditional forecast factors, and any relevant non-warning hazard/risk signals. - -In most cases: - -- Provide 2–3 sentences summarizing the relevant local/regional setup. -- Provide 1–2 sentences describing the main forecast uncertainty or conditional factor, if present. -- Optionally include 1–2 sentences about the next day or broader pattern if supported. - -# STYLE RULES - -- Plainspoken, precise, and weather-literate. -- Compact, but not shallow. -- No generic public-safety filler. -- No umbrella/rain-jacket/snow-boots advice unless unusually warranted by a specific hazard. -- No commute or outdoor-plan boilerplate. -- No unsupported precision. -- No raw YAML, raw JSON, internal field names, source hashes, endpoint names, URLs, implementation details, or debugging notes. -- No apologies for missing data. -- Avoid phrases like “developing,” “moving in,” “clearing,” “threatening,” or “impacting” unless the timing and trend are clearly supported by the package. -- Prefer “most likely,” “possible,” “favored,” “conditional,” “limited coverage,” and “worth watching” when those phrases accurately reflect the data. \ No newline at end of file diff --git a/docs/roadmap/scriptorium/prompts/daily_report/daily_report.yml b/docs/roadmap/scriptorium/prompts/daily_report/daily_report.yml deleted file mode 100644 index 6b81cee..0000000 --- a/docs/roadmap/scriptorium/prompts/daily_report/daily_report.yml +++ /dev/null @@ -1,24 +0,0 @@ -id: weather.daily_report -version: "1.0.0" -#default_profile: local-heavy -default_profile: gemini-3-flash-lite -description: Daily weather report prompt. -inputs: - - name: data_package - required: true - content_type: application/json - description: Structured weather data package -messages: - - role: system - content_file: ./daily_report.system.md - - role: user - content_file: ./daily_report.user.md - - role: user - content: | - <<>> -output: - format: markdown - validation_mode: basic - repair_attempts: 0 diff --git a/docs/roadmap/scriptorium/prompts/hourly/hourly_generated_text.user.md b/docs/roadmap/scriptorium/prompts/hourly/hourly_generated_text.user.md deleted file mode 100644 index 56f2743..0000000 --- a/docs/roadmap/scriptorium/prompts/hourly/hourly_generated_text.user.md +++ /dev/null @@ -1,55 +0,0 @@ -TASK: You are writing structured prose slots for a short-term hourly weather report. - -The calling application will render the final Markdown report. Your job is not to write the full report. Return only a JSON object matching the configured schema. - -Use only the supplied `data_package`. Do not invent weather details, times, hazards, probabilities, or impacts that are not supported by the data. - -The report focuses on the valid period in `report.valid_period`, typically the next several hours for the configured location. - -Return these fields: - -- `summary`: required. 1-2 sentences summarizing the main weather story for the valid period. -- `forecast_discussion`: required. 2-3 sentences explaining the broader setup, trend, or forecast reasoning most relevant to the valid period. -- `precipitation_timing`: optional. Include only when the deterministic `precip_timing` module contains precipitation windows. - -Return JSON only. - -# summary - -The summary should typically consist of two sentences. - -If an active warning is relevant during the report period, lead with the hazard. Otherwise, the first sentence should state the most likely local weather outcome for the valid period, including the overall character of the weather and expected temperature/temperature range. - -If the forecast indicates a significant shift in conditions over time (e.g., from sunny to overcast), then identify the hour when the shift is most likely to occur. If the conditions are generally similar or stable across the forecast period, then pick a single descriptor (e.g., mostly clear) that best captures the character of the weather. - -The second sentence should state the most important active hazard, caveat, uncertainty, or alternate outcome, if one exists. If there is no meaningful caveat, the second sentence may be omitted, or may briefly say that no major complications are apparent. - -In the lead, distinguish the main weather outcome from the caveat. If showers and thunderstorms have different timing, state that difference rather than combining them as a single risk throughout the valid period. If the main caveat is a regional severe-weather or precipitation risk displaced from the report location, state that limitation clearly. - -Example style: - -- “The rest of the afternoon is expected to be warm and dry, with mostly clear skies. There is a slight chance of isolated showers and thunderstorms developing from late afternoon into early evening.” - -# forecast_discussion - -Use narrative products to explain the “why” behind the local forecast when useful. - -Useful context may include: - -- synoptic pattern -- fronts or boundaries -- shortwaves, troughs, or ridges -- instability, moisture, shear, forcing, or capping -- regional placement of precipitation or severe-weather chances -- hazard types and timing windows -- confidence or uncertainty -- conditional outcomes -- relevant notes about the following day or days - -# precipitation_timing - -Optional. Return only if precipitation is forecast. If present, provide 1 to 4 sentences to add practical context, including: - - - Whether the precipitation is associated with a moving frontal boundary, convective initiation, or wide stratiform rain (if this can be determined from the data package); - - The expected type, intensity, and duration of the precipitation; and - - Any caveats or uncertainty with respect to the onset, duration, or occurrance of the precipitation. diff --git a/docs/roadmap/scriptorium/prompts/hourly/hourly_generated_text.yml b/docs/roadmap/scriptorium/prompts/hourly/hourly_generated_text.yml deleted file mode 100644 index daa1fb0..0000000 --- a/docs/roadmap/scriptorium/prompts/hourly/hourly_generated_text.yml +++ /dev/null @@ -1,25 +0,0 @@ -id: weather.hourly_generated_text -version: "1.0.0" -default_profile: local-heavy -#default_profile: gemini-3-flash-lite -description: Hourly weather report analysis prompt. -inputs: - - name: data_package - required: true - content_type: application/json - description: Structured weather data package -messages: - - role: system - content_file: ../common/system.md - - role: user - content_file: ../common/data_package.user.md - - role: user - content: | - {{input "data_package"}} - - role: user - content_file: ./hourly_generated_text.user.md -output: - format: json - validation_mode: json_schema - schema_path: pipeline-weather/hourly/hourly.generated_text.schema.json - repair_attempts: 2 \ No newline at end of file diff --git a/docs/roadmap/scriptorium/prompts/today/today_generated_text.user.md b/docs/roadmap/scriptorium/prompts/today/today_generated_text.user.md deleted file mode 100644 index 1e244cd..0000000 --- a/docs/roadmap/scriptorium/prompts/today/today_generated_text.user.md +++ /dev/null @@ -1,57 +0,0 @@ -TASK: You are writing structured prose slots for a daily weather report. - -The calling application will render the final Markdown report. Your job is not to write the full report. Return only a JSON object matching the configured schema. - -Use only the supplied `data_package`. Do not invent weather details, times, hazards, probabilities, or impacts that are not supported by the data. - -The report focuses on the valid period in `report.valid_period`, which corresponds to the current civil day (today) for the configured location. - -Return these fields: - -- `summary`: required. 1-2 sentences summarizing the main weather story for the valid period. -- `forecast_discussion`: required. 3 paragraphs explaining the broader setup, trend, and/or forecast reasoning most relevant to the valid period. -- `precipitation_timing`: optional. Include only when the deterministic `precip_timing` module contains precipitation windows. - -Return JSON only. - -# summary - -The summary should typically consist of two sentences. - -If an active warning is relevant during the report period, lead with the hazard. Otherwise, the first sentence should state the most likely local weather outcome for the valid period, including the overall character of the weather and expected temperature/temperature range. - -The second sentence should state the most important active hazard, caveat, uncertainty, or alternate outcome, if one exists. If there is no meaningful caveat, the second sentence may be omitted. - -In the lead, distinguish the main weather outcome from the caveat. If showers and thunderstorms have different timing, state that difference rather than combining them as a single risk throughout the valid period. If the main caveat is a regional severe-weather or precipitation risk displaced from the report location, state that limitation clearly. - -Example style: - -- “Today is expected to be warm and dry, with mostly clear skies. There is a slight chance of isolated showers and thunderstorms developing from late afternoon into early evening.” - -# forecast_discussion - -Use narrative products to explain the “why” behind the local forecast when useful. Useful context may include: - -- synoptic pattern -- fronts or boundaries -- shortwaves, troughs, or ridges -- instability, moisture, shear, forcing, or capping -- regional placement of precipitation or severe-weather chances -- hazard types and timing windows -- confidence or uncertainty -- conditional outcomes -- relevant notes about the following day or days - -In most cases, the `forecast_discussion` should include three paragraphs: - -1. 2–4 sentences summarizing the relevant local/regional setup. -2. 2-4 sentences describing the main forecast uncertainty or conditional factor, if present. -3. 2-4 sentences about the next day or broader pattern if supported. - -# precipitation_timing - -Optional. Return only if precipitation is forecast. If present, provide 1 to 4 sentences to add practical context, including: - - - Whether the precipitation is associated with a moving frontal boundary, convective initiation, or wide stratiform rain (if this can be determined from the data package); - - The expected type, intensity, and duration of the precipitation; and - - Any caveats or uncertainty with respect to the onset, duration, or occurrance of the precipitation. diff --git a/docs/roadmap/scriptorium/prompts/today/today_generated_text.yml b/docs/roadmap/scriptorium/prompts/today/today_generated_text.yml deleted file mode 100644 index fa6227c..0000000 --- a/docs/roadmap/scriptorium/prompts/today/today_generated_text.yml +++ /dev/null @@ -1,25 +0,0 @@ -id: weather.today_generated_text -version: "1.0.0" -default_profile: local-heavy -#default_profile: gemini-3-flash-lite -description: Today's weather report analysis prompt. -inputs: - - name: data_package - required: true - content_type: application/json - description: Structured weather data package -messages: - - role: system - content_file: ../common/system.md - - role: user - content_file: ../common/data_package.user.md - - role: user - content: | - {{input "data_package"}} - - role: user - content_file: ./today_generated_text.user.md -output: - format: json - validation_mode: json_schema - schema_path: pipeline-weather/today/today.generated_text.schema.json - repair_attempts: 2 \ No newline at end of file diff --git a/docs/roadmap/scriptorium/prompts/tomorrow/tomorrow_generated_text.user.md b/docs/roadmap/scriptorium/prompts/tomorrow/tomorrow_generated_text.user.md deleted file mode 100644 index 9294334..0000000 --- a/docs/roadmap/scriptorium/prompts/tomorrow/tomorrow_generated_text.user.md +++ /dev/null @@ -1,58 +0,0 @@ -TASK: You are writing structured prose slots for a daily weather report. - -The calling application will render the final Markdown report. Your job is not to write the full report. Return only a JSON object matching the configured schema. - -Use only the supplied `data_package`. Do not invent weather details, times, hazards, probabilities, or impacts that are not supported by the data. - -The report focuses on the valid period in `report.valid_period`, which corresponds to the next civil day (tomorrow) for the configured location. - -Return these fields: - -- `summary`: required. 1-2 sentences summarizing the main weather story for the valid period. -- `forecast_discussion`: required. 3 paragraphs explaining the broader setup, trend, and/or forecast reasoning most relevant to the valid period. -- `precipitation_timing`: optional. Include only when the deterministic `precip_timing` module contains precipitation windows. -- `confidence`: optional. Include only if uncertainty, timing spread, or conflicting signals materially affect how the reader should interpret the forecast. - -Return JSON only. - -# summary - -The summary should typically consist of two sentences. - -If an active warning is relevant during the report period, lead with the hazard. Otherwise, the first sentence should state the most likely local weather outcome for the valid period, including the overall character of the weather and expected temperature/temperature range. - -The second sentence should state the most important active hazard, caveat, uncertainty, or alternate outcome, if one exists. If there is no meaningful caveat, the second sentence may be omitted. - -In the lead, distinguish the main weather outcome from the caveat. If showers and thunderstorms have different timing, state that difference rather than combining them as a single risk throughout the valid period. If the main caveat is a regional severe-weather or precipitation risk displaced from the report location, state that limitation clearly. - -Example style: - -- “Sunday is expected to be warm and dry, with mostly clear skies. There is a slight chance of isolated showers and thunderstorms developing from late afternoon into early evening.” - -# forecast_discussion - -Use narrative products to explain the “why” behind the local forecast when useful. Useful context may include: - -- synoptic pattern -- fronts or boundaries -- shortwaves, troughs, or ridges -- instability, moisture, shear, forcing, or capping -- regional placement of precipitation or severe-weather chances -- hazard types and timing windows -- confidence or uncertainty -- conditional outcomes -- relevant notes about the following day or days - -In most cases, the `forecast_discussion` should include three paragraphs: - -1. 2–4 sentences summarizing the relevant local/regional setup. -2. 2-4 sentences describing the main forecast uncertainty or conditional factor, if present. -3. 2-4 sentences about the next day or broader pattern if supported. - -# precipitation_timing - -Use 1-2 sentences to add practical context, including: - - - Whether the precipitation is associated with a moving frontal boundary, convective initiation, or wide stratiform rain (if this can be determined from the data package); - - The expected type, intensity, and duration of the precipitation; and - - Any caveats or uncertainty with respect to the onset, duration, or occurrance of the precipitation. diff --git a/docs/roadmap/scriptorium/prompts/tomorrow/tomorrow_generated_text.yml b/docs/roadmap/scriptorium/prompts/tomorrow/tomorrow_generated_text.yml deleted file mode 100644 index 4984350..0000000 --- a/docs/roadmap/scriptorium/prompts/tomorrow/tomorrow_generated_text.yml +++ /dev/null @@ -1,25 +0,0 @@ -id: weather.tomorrow_generated_text -version: "1.0.0" -default_profile: local-heavy -#default_profile: gemini-3-flash-lite -description: Tomorrow's weather report analysis prompt. -inputs: - - name: data_package - required: true - content_type: application/json - description: Structured weather data package -messages: - - role: system - content_file: ../common/system.md - - role: user - content_file: ../common/data_package.user.md - - role: user - content: | - {{input "data_package"}} - - role: user - content_file: ./tomorrow_generated_text.user.md -output: - format: json - validation_mode: json_schema - schema_path: pipeline-weather/tomorrow/tomorrow.generated_text.schema.json - repair_attempts: 2 \ No newline at end of file diff --git a/docs/roadmap/scriptorium/schemas/daily/daily.generated_text.schema.json b/docs/roadmap/scriptorium/schemas/daily/daily.generated_text.schema.json deleted file mode 100644 index c3946bb..0000000 --- a/docs/roadmap/scriptorium/schemas/daily/daily.generated_text.schema.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "weatherreporter.today.generated_text.schema.json", - "title": "Today GeneratedText", - "type": "object", - "additionalProperties": false, - "required": [ - "summary", - "forecast_discussion" - ], - "properties": { - "summary": { - "type": "string" - }, - "forecast_discussion": { - "type": "array", - "items": { - "type": "string" - }, - "minItems": 1 - }, - "precipitation_timing": { - "type": "string" - } - } -} diff --git a/docs/roadmap/scriptorium/schemas/hourly/hourly.generated_text.schema.json b/docs/roadmap/scriptorium/schemas/hourly/hourly.generated_text.schema.json deleted file mode 100644 index ffe45f1..0000000 --- a/docs/roadmap/scriptorium/schemas/hourly/hourly.generated_text.schema.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "weatherreporter.hourly.generated_text.schema.json", - "title": "Hourly GeneratedText", - "type": "object", - "additionalProperties": false, - "required": [ - "summary", - "forecast_discussion" - ], - "properties": { - "summary": { - "type": "string" - }, - "forecast_discussion": { - "type": "string" - }, - "precipitation_timing": { - "type": "string" - } - } -} diff --git a/docs/roadmap/scriptorium/schemas/today/today.generated_text.schema.json b/docs/roadmap/scriptorium/schemas/today/today.generated_text.schema.json deleted file mode 100644 index c3946bb..0000000 --- a/docs/roadmap/scriptorium/schemas/today/today.generated_text.schema.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "weatherreporter.today.generated_text.schema.json", - "title": "Today GeneratedText", - "type": "object", - "additionalProperties": false, - "required": [ - "summary", - "forecast_discussion" - ], - "properties": { - "summary": { - "type": "string" - }, - "forecast_discussion": { - "type": "array", - "items": { - "type": "string" - }, - "minItems": 1 - }, - "precipitation_timing": { - "type": "string" - } - } -} diff --git a/docs/roadmap/scriptorium/schemas/tomorrow/tomorrow.generated_text.schema.json b/docs/roadmap/scriptorium/schemas/tomorrow/tomorrow.generated_text.schema.json deleted file mode 100644 index e03f717..0000000 --- a/docs/roadmap/scriptorium/schemas/tomorrow/tomorrow.generated_text.schema.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "weatherreporter.tomorrow.generated_text.schema.json", - "title": "Tomorrow GeneratedText", - "type": "object", - "additionalProperties": false, - "required": [ - "summary", - "forecast_discussion" - ], - "properties": { - "summary": { - "type": "string" - }, - "forecast_discussion": { - "type": "array", - "items": { - "type": "string" - }, - "minItems": 1 - }, - "precipitation_timing": { - "type": "string" - } - } -} diff --git a/docs/templates.md b/docs/templates.md index a6b4db0..3d8c50d 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -97,7 +97,7 @@ fields: | Field | Purpose | | --- | --- | | `.Report` | Display labels and canonical report timing metadata. | -| `.GeneratedText` | Validated prose supplied by Scriptorium. | +| `.GeneratedText` | Validated prose supplied by Promptkit. | | `.Modules` | Deterministic, typed values prepared for Markdown rendering. | | `.Collected` | Normalized upstream facts for advanced use. | | `.Derived` | Shared calculated facts for advanced use. | @@ -121,7 +121,7 @@ of formatting timestamps in a template. ### Validated GeneratedText Prose -GeneratedText is prose returned by Scriptorium and validated before rendering. +GeneratedText is prose returned by Promptkit and validated before rendering. It is not a source for deterministic weather facts. | Field | Hourly type | Daily, Today, and Tomorrow type | Notes | diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index b66703d..27e0ce1 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -1,271 +1,48 @@ # Troubleshooting -Use the error from the command together with the run artifacts when a run ID is -available. Start with [`inspect metadata`](cli.md#inspection-commands) to identify the -report and artifact paths, then use the narrower inspection command named -below. Do not remove a workspace to diagnose a failure: it contains the -evidence needed to correct it safely. +Keep failed workspace artifacts in place. When a RunID is available, start +with `weatherreporter inspect metadata RUN_ID` and use the paths in its result. -## A command or configuration is rejected before work starts +## Prompt inspection or credentials fail before collection -Symptom: The command exits before it creates a run, with an unknown-flag, -missing-argument, invalid date or time bound, invalid timezone, or -`weather_api.base_url` message. +A prompt/version, contract, selected profile, unsupported direct-key profile, +or required environment credential can fail before weather collection. Correct +the configured `promptkit` profile or profile source, confirm the exact +Promptkit asset is available, and supply any reported environment credential. +Do not add provider keys to YAML. See [configuration](config.md). -Likely cause: The command does not accept that option for the requested report, -or required command and configuration values are absent or malformed. +## Preparation, capacity, or execution fails -Diagnostic: Compare the command with [`generate` and `run`](cli.md#commands-and-usage) -and review the configured value named in the error. `generate daily` requires -`--date`. - -Safe fix: Correct only the reported option or configuration value. Use an -absolute Weather API URL and a valid IANA timezone; do not change unrelated -workspace data. - -See also: [Configuration](config.md) and [Weather API integration](integrations/weatherapi.md). - -## Weather data cannot be collected - -Symptom: A generation command fails while fetching weather data, or reports -`hourly forecast data is missing` or `contains no periods`. - -Likely cause: The Weather API is unavailable, its configured endpoint or -credentials are unsuitable, or the response lacks the hourly forecast required -by the selected report. - -Diagnostic: Check the service status and the configured base URL, then retry -the same report. If a run ID was produced, run `weatherreporter inspect sources -RUN_ID` to see the recorded source result. - -Safe fix: Restore access to the configured Weather API or choose a reporting -period supported by the returned forecast. Do not invent missing hourly values -in local artifacts. - -See also: [Configuration](config.md) and [Weather API integration](integrations/weatherapi.md). - -## Optional source warnings appear - -Symptom: The report succeeds but its output says that a source supplied a -warning or degraded result. - -Likely cause: An optional source did not return usable data; mandatory weather -collection still completed. - -Diagnostic: Run `weatherreporter inspect sources RUN_ID` and identify the -source and warning recorded for that run. - -Safe fix: Correct the affected source configuration or service issue, then -generate a new report if the missing optional information is needed. Keep the -existing run for comparison. - -See also: [Inspecting a run](cli.md#inspection-commands) and [Operations](operations.md). - -## Scriptorium cannot be prepared - -Symptom: The report fails with a fragment such as `run scriptorium render`, or -the Scriptorium executable cannot be started. - -Likely cause: The configured executable, profile, prompt, or its local runtime -environment is unavailable to Weatherreporter. - -Diagnostic: Confirm that the configured executable can be run by the same user -and inspect `weatherreporter inspect metadata RUN_ID` when a run ID is shown. - -Safe fix: Repair the executable path or the Scriptorium configuration and retry -the report. Do not edit generated artifacts to bypass preparation. - -See also: [Configuration](config.md) and [Operations](operations.md). - -## Scriptorium preflight fails - -Symptom: A Scriptorium-backed report stops before text generation, often with -a `scriptorium render exited with code` fragment. - -Likely cause: Scriptorium rejected the render request, prompt, profile, or data -package before it could run the report. - -Diagnostic: Inspect the run metadata and the saved preflight artifact path it -references. Compare the reported Scriptorium diagnostic with its configuration. - -Safe fix: Correct the reported Scriptorium input or configuration, then create -a new run. Preserve the failed preflight artifact for support or comparison. - -See also: [Inspecting a run](cli.md#inspection-commands) and [Operations](operations.md). - -## Scriptorium report execution fails - -Symptom: Preparation succeeded, but generation stops with a -`scriptorium run exited with code` fragment. - -Likely cause: The Scriptorium run failed after preflight, for example because -its prompt execution or runtime dependency failed. - -Diagnostic: Inspect the run metadata and preflight artifact, then review the -exit diagnostic from the command. This distinguishes a run failure from a -preflight failure. - -Safe fix: Correct the Scriptorium issue identified by that diagnostic and run -the report again; leave the failed run artifacts in place. - -See also: [Operations](operations.md). +A preparation failure occurs before provider work; an execution failure occurs +after preparation. Both leave safe provenance and metadata when reached. A +capacity error for one batch report does not retry that report or prevent later +independent reports. Inspect the preparation or execution path, correct the +profile/backend condition, and create a new run. See [operations](operations.md). ## Generated text fails validation -Symptom: A generated-text report fails after Scriptorium returns text, with a -message about generated text or required report content. +Raw generated output may be saved but Markdown is not rendered when the JSON +does not match the report schema. Correct the Promptkit prompt/profile behavior +or the matching schema and validator in source control; do not edit raw output +to treat it as validated. See [templates](templates.md). -Likely cause: Returned text does not meet the report's validation rules. +## Debug capture fails -Diagnostic: Use `weatherreporter inspect metadata RUN_ID` to find the saved raw -generated-text artifact, and inspect it alongside the reported validation -message. +`--llm-debug-dir` must be an absolute secure directory outside workspace state. +A debug-write failure stops the affected report to avoid continuing without the +requested diagnostic. Repair the named path's ownership or permissions, then +rerun. Treat capture files as sensitive. See [operations](operations.md). -Safe fix: Correct the upstream prompt or generation configuration that caused -the invalid output, then create a new run. Do not hand-edit saved raw text and -present it as a validated report. +## Weather, state, output, or notification fails -See also: [Operations](operations.md). - -## Report template rendering fails - -Symptom: Scriptorium output is available, but the report fails while building -the final Markdown document. - -Likely cause: The selected report template or the render context is -incompatible with the generated or collected data. - -Diagnostic: Inspect the metadata, generated-text result, and render-context -artifacts for the run. Note the template or missing-field fragment in the -error rather than relying on a complete error string. - -Safe fix: Correct the template or its supported inputs in source control, test -the change, and create a new report. Do not alter the saved context merely to -make one historical run render. - -See also: [Operations](operations.md). - -## A report fails after artifacts are saved - -Symptom: A generation command reports an error after showing a run ID, such as -an error writing the managed report, copying `--out`, saving metadata, or -notifying Distributor. - -Likely cause: A local filesystem permission or path problem, an unavailable -destination for `--out`, or a later report-delivery failure occurred after -earlier steps succeeded. - -Diagnostic: Run `weatherreporter inspect metadata RUN_ID` and check the exact -path and operation named in the error. For an `--out` failure, verify only the -specified destination directory and filename. - -Safe fix: Repair access to that exact path or disable the optional delivery -step only when appropriate, then generate a new report. Keep the existing -managed artifacts untouched. - -See also: [Operations](operations.md) and [Distributor integration](integrations/distributor/pkg-upload.md). - -## A batch has partial report failures - -Symptom: `run morning` or `run evening` returns nonzero and reports both -succeeded and failed report items. - -Likely cause: A report-level collection, generation, rendering, or local -output failure affected one or more planned reports; the remaining reports -continue independently. - -Diagnostic: Read the per-report status lines, then inspect the run ID for each -failed item with `weatherreporter inspect metadata RUN_ID`. - -Safe fix: Correct the specific failure and rerun the batch or affected report. -Do not delete successful reports simply because another item failed. - -See also: [Batch commands](cli.md#commands-and-usage) and [Operations](operations.md). - -## A batch upload is skipped - -Symptom: The batch result says Distributor notification was skipped because -one or more reports failed. - -Likely cause: Batch notification intentionally runs only after every planned -report succeeds. - -Diagnostic: Review the failed report items and their metadata; a skipped batch -notification is expected while any item is failed. - -Safe fix: Resolve the report failures and rerun the batch. Do not upload a -partial bundle by manually reusing batch artifacts. - -See also: [Batch commands](cli.md#commands-and-usage) and [Operations](operations.md). - -## Distributor notification fails - -Symptom: A completed report or otherwise successful batch reports a Distributor -error, including a rejected upload, source or idempotency conflict, or service -unavailability. - -Likely cause: Distributor rejected the request identity or bundle, required -credentials are unavailable, or the remote service cannot be reached. - -Diagnostic: Inspect the report metadata or batch result for the notification -artifact and the error fragment. Verify the configured Distributor endpoint and -request identity without exposing credentials. - -Safe fix: Resolve the reported remote conflict, configuration, or availability -issue and create a new report or rerun the batch. Do not modify recorded bundle -or idempotency artifacts to force an upload. - -See also: [Configuration](config.md), [Distributor integration](integrations/distributor/pkg-upload.md), and [Operations](operations.md). +Collection errors precede planning. Later filesystem, output-copy, template, +or Distributor errors retain the reached safe paths in the summary. Repair only +the reported endpoint or path, leave successful managed reports intact, and +rerun the affected report or batch. A batch notification is intentionally +skipped when any report item fails. ## Secrets cannot be loaded -Symptom: Startup reports `read secrets directory`, `secret file`, or a token -environment-variable error before the affected service can be used. - -Likely cause: The configured secrets directory cannot be read, contains a -non-regular file, or does not supply the environment variable required by an -enabled integration. - -Diagnostic: Check the configured secrets directory path, ownership, and that -each intended secret is a regular file. Confirm the variable name from -configuration only; never print or paste its value. - -Safe fix: Correct permissions, file type, or the missing secret file, then -retry. Keep secret values out of commands, logs, tickets, and artifacts. - -See also: [Configuration](config.md) and [Operations](operations.md). - -## A run ID or saved state cannot be found - -Symptom: An inspection command reports that metadata for a run ID was not -found, or a report cannot use a prior snapshot. - -Likely cause: The run ID is wrong, the configured workspace is different from -the one that created the run, or no compatible prior snapshot exists. - -Diagnostic: Use `weatherreporter inspect reports` to list available reports in -the current workspace, then copy the run ID from that output. Confirm the -workspace configuration before retrying a prior-snapshot operation. - -Safe fix: Use an existing run ID and its original workspace, or generate a new -compatible report when no prior snapshot is available. Do not fabricate state -files or run IDs. - -See also: [Inspecting a run](cli.md#inspection-commands) and [Operations](operations.md). - -## Workspace paths cannot be read or written - -Symptom: Startup or report persistence reports a workspace-path, permission, -or "must be relative to workspace root" error. - -Likely cause: A configured artifact directory escapes the workspace, or the -current user lacks access to the specific workspace location. - -Diagnostic: Check the named configuration path against the configured workspace -root and inspect ownership and permissions of that exact directory. - -Safe fix: Set the path to a location within the workspace or repair access to -the named directory, then rerun. Do not remove the workspace or broadly relax -permissions. - -See also: [Configuration](config.md) and [Operations](operations.md). +Secret files must be regular non-symlink files directly beneath +`secrets.directory` with valid environment-variable basenames. Correct the +reported file or directory without placing secret values in YAML.