Reconcile internal stateless documentation

This commit is contained in:
2026-08-01 20:16:47 +00:00
parent bd34ec57f8
commit 71a2eae87b
18 changed files with 78 additions and 347 deletions

View File

@@ -58,8 +58,8 @@ application to record.
Run and idempotency records are in-memory. Completed records expire according Run and idempotency records are in-memory. Completed records expire according
to Distributor's `server.http.retention`, and a Distributor restart removes to Distributor's `server.http.retention`, and a Distributor restart removes
retained status and idempotency state. Status polling decisions and persistence retained status and idempotency state. Status polling decisions are internal
of notification artifacts are internal orchestration behavior; see the orchestration behavior; see the
[Distributor adapter](../../internal/distributor-adapter.md) and [Distributor adapter](../../internal/distributor-adapter.md) and
[application orchestration](../../internal/app-orchestration.md). [application orchestration](../../internal/app-orchestration.md).

View File

@@ -8,15 +8,15 @@ the upload call returns.
## File Mappings ## File Mappings
Every mapping pairs a managed Markdown report source with one bundle-relative Every mapping pairs an operator-owned Markdown output with one bundle-relative
path. A single-report notification maps its one managed report to each rendered path. A single-report notification maps its published output to each rendered
path configured for that report. A batch notification combines mappings for path configured for that report. A batch notification combines mappings for
every included managed report and rejects duplicate bundle paths. every included published output and rejects duplicate bundle paths.
The report source is never an `--out` copy or an arbitrary workspace scan. The The report source is the output selected for that command; the application does
application selects it and renders notification paths; see the [operations guide](../../operations.md) not scan local directories. It renders notification paths after publication;
for the managed-upload rule and the [Distributor adapter](../../internal/distributor-adapter.md) see the [operations guide](../../operations.md) and the
for the adapter boundary. [Distributor adapter](../../internal/distributor-adapter.md) for the boundary.
Bundle paths must be clean, relative, slash-separated paths. They cannot be Bundle paths must be clean, relative, slash-separated paths. They cannot be
empty or absolute, contain backslashes, empty segments, `.` or `..`, or use empty or absolute, contain backslashes, empty segments, `.` or `..`, or use

View File

@@ -16,7 +16,7 @@ For each notification, Weatherreporter calls `UploadFiles` with:
- the rendered pipeline ID; - the rendered pipeline ID;
- the rendered bundle ID as the source manifest ID; - the rendered bundle ID as the source manifest ID;
- the report or batch generation time as `Created`; - the report or batch generation time as `Created`;
- the managed-report-to-bundle-path mappings described in the - the published-output-to-bundle-path mappings described in the
[bundle mapping contract](pkg-bundle.md); and [bundle mapping contract](pkg-bundle.md); and
- a rendered idempotency key. - a rendered idempotency key.
@@ -38,8 +38,8 @@ adapter translates it to its own conflict error without exposing the token.
The adapter then calls `Status` for the accepted run. A terminal `failed` The adapter then calls `Status` for the accepted run. A terminal `failed`
status is a notification failure. A status lookup failure or a timeout before a status is a notification failure. A status lookup failure or a timeout before a
terminal status remains attached to the otherwise accepted upload as diagnostic terminal status remains attached to the otherwise accepted upload as diagnostic
status information. Polling cadence, final failure handling, redaction, and status information. Polling cadence, final failure handling, and redaction are
notification artifact persistence are internal behavior documented in the internal behavior documented in the
[Distributor adapter](../../internal/distributor-adapter.md) and [Distributor adapter](../../internal/distributor-adapter.md) and
[application orchestration](../../internal/app-orchestration.md). [application orchestration](../../internal/app-orchestration.md).

View File

@@ -1,15 +1,10 @@
# Promptkit Integration # Promptkit Integration
Weatherreporter uses Promptkit for all generated-text reports. The four logical 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 `2.0.0`. Their prompt assets, generated-text JSON Schemas, and Weatherreporter profile catalog are embedded by `internal/promptassets`.
prompts are `weather.daily_generated_text`, `weather.today_generated_text`,
`weather.tomorrow_generated_text`, and `weather.hourly_generated_text`, each at
version `1.1.0`. Their prompt assets, generated-text JSON Schemas, and
Weatherreporter profile catalog are embedded by `internal/promptassets`.
## Logical profile catalog ## Logical Profile Catalog
Prompt definitions select a stable Weatherreporter profile ID. The embedded Prompt definitions select a stable Weatherreporter profile ID. The embedded definitions currently use Promptkit's `openrouter` backend:
definitions currently use Promptkit's `openrouter` backend:
| Profile ID | Model | Reasoning effort | Timeout | Service tier | Default reports | | Profile ID | Model | Reasoning effort | Timeout | Service tier | Default reports |
| --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- |
@@ -17,44 +12,23 @@ definitions currently use Promptkit's `openrouter` backend:
| `weather-balanced` | `~google/gemini-flash-latest` | `high` | 240 seconds | `flex` | Daily, Today, Tomorrow | | `weather-balanced` | `~google/gemini-flash-latest` | `high` | 240 seconds | `flex` | Daily, Today, Tomorrow |
| `weather-deep` | `~anthropic/claude-sonnet-latest` | `high` | 240 seconds | `flex` | None | | `weather-deep` | `~anthropic/claude-sonnet-latest` | `high` | 240 seconds | `flex` | None |
The `~` prefix is part of each OpenRouter rolling-alias model ID. The embedded The `~` prefix is part of each OpenRouter rolling-alias model ID. The embedded profiles intentionally omit endpoints, credentials, temperature, `top_p`, and output-token limits.
profiles intentionally omit endpoints, credentials, temperature, `top_p`, and
output-token limits.
## Selection, lookup, and active execution ## Selection And Active Execution
Before collection, Weatherreporter inspects the exact prompt version and output Before weather collection, Weatherreporter validates the exact prompt version, output contract, and selected profile. A nonblank `promptkit.profile` selects one profile ID for every report in the command; otherwise the prompt's declared default selects it. Promptkit resolves the selected definition in this order:
contract. A nonblank `promptkit.profile` selects one profile ID for every
report in the command; otherwise the prompt's declared default selects it.
Promptkit resolves the selected definition in this order:
1. explicit in-memory profiles used by an embedding consumer or test; 1. explicit in-memory profiles used by an embedding consumer or test;
2. the configured `profile_file` or `profile_dir`; 2. the configured `profile_file` or `profile_dir`;
3. Weatherreporter's embedded fallback profiles; and 3. Weatherreporter's embedded fallback profiles; and
4. Promptkit's built-in catalog. 4. Promptkit's built-in catalog.
A source falls through only when the selected ID is absent. Each source A source falls through only when the selected ID is absent. Each source supplies a complete definition, so profile fields are not merged. A malformed matching operator definition is an error and does not fall back.
supplies a complete definition, so profile fields are not merged. A malformed
matching operator definition is an error and does not fall back.
Profiles that require a direct API key are unsupported; a profile that reports Profiles that require a direct API key are unsupported; a profile that reports `APIKeyEnv` requires a nonblank value in that environment variable. Active results retain the selected logical profile ID and resolved backend and model. Ordinary errors, summaries, logs, and outputs exclude endpoints, credentials, rendered messages, schemas, request bodies, response bodies, and complete parameter maps.
`APIKeyEnv` requires a nonblank value in that environment variable. Inspection,
preparation, and execution retain the selected logical profile ID and resolved
backend and model through Weatherreporter's project-owned contract. Ordinary
errors, summaries, logs, and workspace state exclude endpoints, credentials,
rendered messages, schemas, request bodies, response bodies, and complete
parameter maps.
Execution receives the already-persisted YAML package, prepares it once, and returns structured Promptkit receives the YAML data package as an inline input and returns structured JSON that Weatherreporter validates before rendering its own Markdown template. Safe active provenance remains in memory. Content-rich diagnostics are opt-in through `--llm-debug-dir`; see [operations](../operations.md) for retention and permissions.
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.
The generated-text schemas require `summary`, `forecast_discussion`, and The generated-text schemas require `summary`, `forecast_discussion`, and `precipitation_timing`, and reject additional properties. Prompts return an empty string for `precipitation_timing` when the deterministic package contains no precipitation windows.
`precipitation_timing`, and reject additional properties. Prompts return an empty string for
`precipitation_timing` when the deterministic package contains no precipitation windows.
Prompt/profile configuration and the maintained local override example are Prompt/profile configuration and the maintained local override example are owned by the [configuration reference](../config.md). Adapter construction and mapping are documented in the [Promptkit adapter internals](../internal/promptkit-adapter.md).
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).

View File

@@ -1,48 +1,24 @@
# Application Orchestration Internals # Application Orchestration Internals
`internal/app` owns top-level generation, batch, collection, inspection, and `internal/app` owns stateless report generation, batch execution, atomic output publication, and notification coordination after `internal/cli` has parsed arguments and loaded configuration. The user contract is owned by the [CLI reference](../cli.md) and [operations guide](../operations.md).
notification ordering after the CLI has parsed arguments and loaded configuration.
## Generation ## Single-Report Flow
`GenerateDetailed` resolves one of the four report definitions, initializes an `GenerateDetailed` resolves the requested report and output destination, then initializes an optional explicit debug writer. It validates the exact Promptkit prompt and selected profile before collecting weather data. The resolved profile, backend, and model are carried in the active result.
optional debug root, and inspects the exact Promptkit prompt/profile before it
collects weather or writes managed state. A configured global profile selects
every report in the action; otherwise the exact prompt selects its default
logical profile. Inspection keeps only the selected profile ID and effective
backend/model needed by the project-owned execution contract. 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.
After a completed prompt run, each successfully written downstream artifact is The workflow builds facts, a module snapshot, briefing metadata, and the YAML prompt package in memory. It executes Promptkit, validates the returned generated text, builds a render context, and renders Markdown. `fileutil` atomically writes the completed Markdown to the selected output path. Only after that write succeeds does single-report notification run.
atomically added to the execution record before the corresponding metadata
rewrite. Later failures therefore leave the original Promptkit outcome and its
last durable set of reached paths inspectable.
Failure results retain all safe paths reached so far. Validation rejection Failures return an active partial result with safe identity, profile, warning, validation, debug, and output information when available. A failure before publication leaves an existing destination unchanged. A notification failure retains the newly published output.
persists raw output and execution provenance but does not render a report.
## Batches ## Batches
`RunBatchDetailed` constructs a single debug writer and uses the request's `RunBatchDetailed` captures one output directory, creates at most one explicit debug writer, and uses one executor. Before collection it validates the prompt and profile candidates for the selected batch. It collects once, calculates the data-dependent plan, and invokes the same generation core sequentially for each planned report.
single executor. Before collection it inspects Today, Tomorrow, and Daily for
morning, or Tomorrow and Daily for evening, deduplicating inspection of a
shared selected profile. 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.
Batch notification is skipped when disabled or when any report failed. Each item has an independent result. A failed item does not stop later items; successful items retain their published output paths. Per-report notification is suppressed during a batch. Batch notification runs only after every planned report has published successfully. It is skipped when any item failed.
Successful notification uses the completed managed report paths only. Batch
items retain preparation, execution, and optional debug paths when reached.
## Inspection And Boundaries ## Boundaries And Verification
Inspection loads persisted state only. It does not collect weather, invoke The package does not parse flags, load YAML, implement transport, construct provider SDKs, or define report-period policy. Prompt, profile, weather, and Distributor implementations remain behind project-owned contracts.
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.
Focused checks: Focused checks:

View File

@@ -66,4 +66,4 @@ go test ./internal/briefing
``` ```
Builders emit structured facts, never report prose. The app collects their Builders emit structured facts, never report prose. The app collects their
outputs into a module snapshot, and state persists that snapshot. outputs into an in-memory module snapshot for prompt input and rendering.

View File

@@ -1,56 +0,0 @@
# Changes Internals
`internal/changes` deterministically compares a compatible prior module
snapshot with the current snapshot. It returns compact structured changes for
prompt input; it never reads state, finds a prior report, renders Markdown, or
compares generated text. Snapshot construction belongs to
[module internals](module.md), and prior-snapshot discovery belongs to
[state internals](state.md).
## Comparison inputs and output
Each comparator receives a prior snapshot, a current snapshot, and
`Thresholds`. A `Change` has a stable type and message plus previous and
current values where useful. Changes are sorted by type and then message, so
the same inputs always yield the same order.
Threshold values are supplied by application orchestration from the
[Recent Changes configuration](../config.md#recent_change); this package does
not load configuration or choose defaults. Numeric changes are emitted when
the absolute difference meets the configured threshold. Precipitation also
requires a change between its low, possible, likely, and high categories.
## Strategies
| Comparator | Required snapshot data | Compared values |
| --- | --- | --- |
| `CompareDaily` | `derived_daily_summary`, `derived_daypart_summaries` | Low and high temperature, daily precipitation probability and timing, peak gust, alerts, and aggregate indicators |
For daily comparison, `alert_digest` and `precip_timing` are optional: alerts
are compared when present, and timing is compared only when both snapshots
contain it.
The application selects a comparator only after state lookup establishes a
compatible prior snapshot. Daily, Today, and Tomorrow use the daily comparator.
Hourly reports do not produce a Recent Changes list.
## Missing data and failures
Required stanzas that are absent or cannot be decoded return an error with the
snapshot and stanza context. Optional stanzas may be absent. A snapshot with no
eligible predecessor is not a comparison failure: the caller supplies an empty
change list without invoking this package.
The package has no filesystem, transport, CLI, renderer, or persistence
behavior. It does not decide report compatibility or retain snapshots.
## Verification and invariants
Focused tests cover the daily strategy, threshold boundaries, indicator and
alert changes, and missing required stanzas:
```sh
go test ./internal/changes
```
Recent Changes always compare structured snapshot values, never report prose.

View File

@@ -1,26 +1,14 @@
# CLI Internals # CLI Internals
`internal/cli` parses terminal arguments, loads configuration, constructs app `internal/cli` parses terminal arguments, loads configuration, constructs app requests, and translates app results to bounded JSON summaries. The public contract belongs in the [CLI reference](../cli.md).
requests, and translates app results to bounded JSON summaries. The user
contract belongs in the [CLI reference](../cli.md).
The root `--version` flag reports the build version supplied by The root `--version` flag reports the build version supplied by `internal/buildinfo`. Tagged release builds replace its development default at link time.
`internal/buildinfo`. Tagged release builds replace its development default at
link time.
For each `generate` or `run` action, `Runner` constructs one project-owned For each `generate` or `run` action, `Runner` constructs one project-owned Promptkit executor after configuration loads. It captures an absolute working directory, resolves a relative output override against it, and passes the working directory, resolved override, and any `--llm-debug-dir` request to the app. With no override, the app derives the report filename in that working directory. `run` uses the same resolution rule for `--out-dir`.
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.
Summaries include identity, status, safe artifact paths, and notification The CLI dispatches only generation and batch actions. It has no persisted-run or inspection dispatch. Summaries include report identity, status, output path, effective profile/backend/model, source warnings, validation, requested debug path, and notification result when available. They intentionally exclude prompt input, raw generated text, render context, endpoints, credentials, and full Distributor payloads. A failed action with a partial result still emits its safe summary before its error is returned.
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.
CLI code owns no report policy, weather collection, persistence, provider CLI code owns no report policy, weather collection, output publication, provider execution, or notification policy. Focused checks:
execution, or notification policy. Focused checks:
```sh ```sh
go test ./internal/cli go test ./internal/cli

View File

@@ -47,7 +47,7 @@ status, and `RunStatus`, including pipeline ID, lifecycle timestamps, report,
and remote error details. and remote error details.
Status lookup or polling errors are preserved in `UploadResult.StatusError` so Status lookup or polling errors are preserved in `UploadResult.StatusError` so
the caller can record an accepted-but-unconfirmed delivery. A terminal failed the caller can report an accepted-but-unconfirmed delivery. A terminal failed
run returns that result and an error. Upload failures return no result. Upstream run returns that result and an error. Upload failures return no result. Upstream
idempotency conflicts become the local `IdempotencyConflictError`, which adds idempotency conflicts become the local `IdempotencyConflictError`, which adds
endpoint, pipeline, bundle, idempotency, and file-path context while redacting endpoint, pipeline, bundle, idempotency, and file-path context while redacting

View File

@@ -60,5 +60,5 @@ go test ./internal/facts
``` ```
Facts are derived once for a resolved report from already collected data. Facts are derived once for a resolved report from already collected data.
They remain reusable structured values: prompt wording, state persistence, They remain reusable structured values for prompt input and template
prior-report comparison, and template presentation are owned elsewhere. presentation, which are owned elsewhere.

View File

@@ -46,9 +46,7 @@ UTC when these APIs are called directly. Optional narrative, discussion, and
alerts remain absent when their normalized products are absent. alerts remain absent when their normalized products are absent.
Forecast thresholds used for brief indicators and precipitation timing are Forecast thresholds used for brief indicators and precipitation timing are
implementation rules. User-configurable Recent Changes thresholds are applied implementation rules.
by [changes internals](changes.md), whose defaults are documented in
[configuration](../config.md).
## Verification and invariants ## Verification and invariants

View File

@@ -34,8 +34,8 @@ template iteration rather than maps.
Optional source stanzas become nil or fallback context fields. Missing required Optional source stanzas become nil or fallback context fields. Missing required
stanzas, type-decoding failures, invalid metadata, or a generated-text type stanzas, type-decoding failures, invalid metadata, or a generated-text type
that does not match the chosen handler fail before template execution. Prompt that does not match the chosen handler fail before template execution. Prompt
packages, raw Promptkit output, state persistence, and template asset lookup packages, raw Promptkit output handling, and template asset lookup remain
remain outside this package. outside this package.
## Verification and invariants ## Verification and invariants

View File

@@ -1,7 +1,7 @@
# Module Contract Internals # Module Contract Internals
`internal/module` defines the stable envelope between report composition, `internal/module` defines the stable envelope between report composition,
module builders, snapshots, comparisons, templates, and prompt packages. It module builders, in-memory snapshots, templates, and prompt packages. It
does not define a report, execute a builder, or choose prompt-export policy; does not define a report, execute a builder, or choose prompt-export policy;
those responsibilities belong to [report registry](report-registry.md) and those responsibilities belong to [report registry](report-registry.md) and
[briefing](briefing.md). [briefing](briefing.md).
@@ -11,10 +11,10 @@ those responsibilities belong to [report registry](report-registry.md) and
Each `Output` has a module ID, stanza name, rich `Value`, and runtime-only Each `Output` has a module ID, stanza name, rich `Value`, and runtime-only
`PromptValue`. `DataPackageValue` returns the prompt value when present and `PromptValue`. `DataPackageValue` returns the prompt value when present and
otherwise the rich value. This permits custom prompt exports without shrinking otherwise the rich value. This permits custom prompt exports without shrinking
the template and inspection value. the template value.
`NewSnapshot` builds the ordered `weatherreporter.modules.v1` snapshot and `NewSnapshot` builds the ordered `weatherreporter.modules.v1` snapshot and
validates it. Snapshot JSON persists IDs, stanza names, and rich values only; validates it. Its JSON representation contains IDs, stanza names, and rich values only;
`PromptValue` is deliberately excluded. `StanzaValue` decodes a named rich `PromptValue` is deliberately excluded. `StanzaValue` decodes a named rich
stanza into a caller-supplied type, reporting a missing stanza separately from stanza into a caller-supplied type, reporting a missing stanza separately from
a decoding error. a decoding error.
@@ -47,7 +47,7 @@ are validated by the briefing registry.
## Rich and prompt-facing values ## Rich and prompt-facing values
Rich values remain available to snapshots, comparisons, and render contexts. Rich values remain available to module snapshots and render contexts.
Briefing attaches custom prompt exports only for current conditions, hourly Briefing attaches custom prompt exports only for current conditions, hourly
forecast, and derived daypart summaries; all other current builders use forecast, and derived daypart summaries; all other current builders use
pass-through values. The prompt package owns how exported stanzas are grouped pass-through values. The prompt package owns how exported stanzas are grouped

View File

@@ -1,29 +1,16 @@
# Prompt Input Internals # Prompt Input Internals
`internal/promptinput` converts report metadata, an ordered module snapshot, `internal/promptinput` converts report metadata, an ordered module snapshot, and source warnings into the YAML `data_package` supplied inline to Promptkit. It owns the package schema, grouping, serialization, loading, and validation; it does not choose an output destination, collect weather, execute a provider, or retain packages after a command ends.
Recent Changes, and source warnings into the YAML `data_package` consumed by
Promptkit. It owns this package's schema, grouping, serialization, loading,
and validation—not weather collection, module construction, path choice, or
provider execution.
## Package construction ## Package Construction
`Build` produces `weatherreporter.data_package.v3`. It copies the run ID; `Build` produces `weatherreporter.data_package.v4`. It copies the run ID; report ID, variant, prompt ID, generation time, timezone, local current date, and valid period; ordered briefing stanzas; and source warnings. Prompt input contains no historical comparison section.
report ID, variant, prompt ID, generation time, timezone, local current date,
and valid period; ordered briefing stanzas; Recent Changes; and source
warnings. A nil Recent Changes slice becomes an empty `items` list.
Briefing starts as a flat snapshot order and stanza-value map. `Build` uses Briefing is a flat ordered set of stanza values. `Build` uses each output's `DataPackageValue`, so curated prompt exports take precedence and rich values are used only as a fallback. Prompt exports are selected by the [briefing registry](briefing.md), while the rich-versus-prompt contract is in [module internals](module.md).
each output's `DataPackageValue`, so runtime prompt exports take precedence and
rich values are used only as a fallback. Prompt exports are selected by the
[briefing registry](briefing.md), while the rich-versus-prompt contract is in
[module internals](module.md).
## YAML ordering and grouping ## YAML Ordering And Validation
Serialization keeps `metadata` directly under `briefing`. Every other known Serialization keeps `metadata` directly under `briefing`. Every other known stanza is placed in one category and emitted in category order while preserving its original module order:
stanza is placed in exactly one category, emitted in category order and in its
original snapshot order within that category:
| Category | Current stanzas | | Category | Current stanzas |
| --- | --- | | --- | --- |
@@ -32,30 +19,10 @@ original snapshot order within that category:
| `narrative_products` | narrative forecast, discussions, and weather story | | `narrative_products` | narrative forecast, discussions, and weather story |
| `raw_data` | current conditions and hourly forecast | | `raw_data` | current conditions and hourly forecast |
This YAML presentation does not alter the flat snapshot model. `LoadYAML` `LoadYAML` accepts this layout and reconstructs the flat order and values. It rejects misplaced, duplicate, unknown, or uncategorized stanzas. `Validate` requires the v4 schema version, report identity and period fields, and at least one ordered briefing stanza. `MarshalYAML` and `LoadYAML` validate their result. `Save` remains a reusable atomic-file helper for callers that explicitly need one; normal application execution passes marshalled YAML directly to Promptkit.
accepts the same category layout and reconstructs flat `Order` and `Values`,
rejecting misplaced, duplicate, unknown, or uncategorized stanzas.
## Validation and persistence Focused tests cover construction, curated exports, category ordering, YAML round trips, invalid layout, validation, and atomic saves:
`Validate` requires the current schema version, run and report identifiers,
prompt ID, generation timestamp, timezone, current local date, valid period,
and at least one ordered briefing stanza. It rejects duplicate stanza names,
missing values, and a missing category for every non-metadata stanza.
`MarshalYAML` and `LoadYAML` validate their result. `Save` writes the serialized
YAML atomically; managed workspace paths are owned by [state internals](state.md).
Generated-text artifacts and template render contexts are later workflow
artifacts, not members of this package.
## Verification and invariants
Focused tests cover construction, curated exports, category ordering, YAML
round trips, invalid layout, validation, and atomic saves:
```sh ```sh
go test ./internal/promptinput go test ./internal/promptinput
``` ```
The package is narrower than a template render context and never infers changes
from report prose.

View File

@@ -1,26 +1,12 @@
# Promptkit Adapter Internals # Promptkit Adapter Internals
`internal/adapters/promptkit` maps Weatherreporter's project-owned executor contract to Promptkit. `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 CLI maps `promptkit` configuration to a `PromptExecutorConfig` and constructs one executor
per action. Promptkit dependency types do not escape the adapter.
The adapter supplies Weatherreporter's embedded prompt, schema, and fallback The adapter supplies Weatherreporter's embedded prompt, schema, and fallback profile filesystems to each engine. Promptkit resolves configured operator profile sources, the embedded fallback catalog, and its built-in catalog; the adapter does not parse profile YAML, merge sources, or probe endpoints.
profile filesystems to each engine. Promptkit remains responsible for resolving
the configured operator profile source, application fallback catalog, and its
built-in catalog; the adapter does not parse profile YAML, merge sources, or
probe endpoints.
The adapter exposes exact prompt and profile inspection plus prepared execution. The adapter exposes exact prompt and profile validation plus prepared execution. It maps safe prompt identity, logical profile, effective backend/model, preparation, execution, validation, and optional debug values into `promptexec`. `Execute` passes the YAML package as an inline Promptkit input; it does not construct a filesystem URI or write a package file.
It maps Promptkit inspection values to project-owned prompt input,
output-contract, logical profile identity, effective backend/model,
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 The application uses the preparation callback to record active safe provenance in memory and optionally writes content-rich diagnostics only through an explicit debug writer. The adapter returns raw output for application validation and rendering. It does not retain application state, render Markdown, choose report definitions, or send Distributor notifications.
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: Focused tests:
@@ -28,5 +14,4 @@ Focused tests:
go test ./internal/adapters/promptkit ./internal/cli ./internal/app go test ./internal/adapters/promptkit ./internal/cli ./internal/app
``` ```
The public logical prompt/profile/schema contract is owned by the The public logical prompt/profile/schema contract is owned by the [Promptkit integration guide](../integrations/promptkit.md).
[Promptkit integration guide](../integrations/promptkit.md).

View File

@@ -1,72 +1,30 @@
# Report Registry Internals # Report Registry Internals
`internal/report` owns the registry of report identities and the data declared `internal/report` owns report identities, valid-period resolution, exact prompt identity and version, output names, default module composition, and Distributor path declarations. Public command syntax belongs in the [CLI reference](../cli.md); configuration aliases and overrides belong in the [configuration reference](../config.md).
for each one: resolution, prompt identity and version, comparison policy,
artifact group, output-copy name, default module composition, and Distributor
path declarations. The public command syntax is owned by the
[CLI reference](../cli.md); configuration aliases and overrides are owned by
the [configuration reference](../config.md).
## Definitions and resolution ## Definitions And Resolution
Each `Definition` declares a stable ID and display name, prompt ID, generation Each `Definition` declares a stable ID and display name, prompt ID and version, template and generated-text schema IDs, valid-period resolver, default output name, Distributor path templates, module list, and fixed batch eligibility. `Resolved` combines a definition with one valid period and run identity.
version, template and generated-text schema IDs, valid-period resolver,
comparison strategy, artifact group, batch-copy filename, Distributor path
templates, generation eligibility, compatible prior IDs, default modules, and
batch eligibility flags. `Resolved` combines that definition with the valid
period and run metadata for one invocation.
| Report ID | Prompt version | Default profile | Period policy | Comparison | Registry batch flag | Output copy | | Report ID | Prompt version | Default profile | Period policy | Fixed batch flag | Default output |
| --- | --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- |
| `daily` | `1.1.0` | `weather-balanced` | Explicit local civil day | Same valid date | Dynamic Daily inclusion is app-owned | `daily.md` | | `daily` | `2.0.0` | `weather-balanced` | Explicit local civil day | Dynamic Daily inclusion is app-owned | `daily-YYYY-MM-DD.md` |
| `today` | `1.1.0` | `weather-balanced` | Selected or current local civil day | Same valid date | Morning | `today.md` | | `today` | `2.0.0` | `weather-balanced` | Selected or current local civil day | Morning | `today.md` |
| `tomorrow` | `1.1.0` | `weather-balanced` | Next local civil day | Same valid date | Evening | `tomorrow.md` | | `tomorrow` | `2.0.0` | `weather-balanced` | Next local civil day | Evening | `tomorrow.md` |
| `hourly` | `1.1.0` | `weather-light` | Rolling six-hour interval | Rolling window | — | `hourly.md` | | `hourly` | `2.0.0` | `weather-light` | Rolling six-hour interval | — | `hourly.md` |
Each report pairs its ID and prompt version with matching template and schema Daily derives its filename from the resolved valid-period start in the effective timezone, so multiple Daily items have distinct destinations. Exact template fields and schema assets belong to [report templates](../templates.md) and [generated-text internals](generatedtext.md). Prompt assets own default profile selection; the registry stores no provider setting.
IDs. Exact template fields and schema assets belong to [report templates](../templates.md)
and [generated-text internals](generatedtext.md). Prompt assets own default
profile selection; the registry deliberately stores no provider setting. The
[Promptkit integration guide](../integrations/promptkit.md) owns profile
definitions and resolution.
All valid periods are half-open. ## Collaborators And Boundaries
## Registry collaborators `DefaultRegistry`, `Lookup`, `Resolve`, and report-name helpers prevent callers from duplicating report identity rules. Registry overrides clone a recognized definition and replace its module list. `DistributorPathTemplates` are consumed by app orchestration; their rendered external bundle-path contract is documented in the [Distributor bundle guide](../integrations/distributor/pkg-bundle.md).
`DefaultRegistry` is the only source of the four report definitions. `morning` and `evening` are registry-owned batch names. Fixed flags declare Today and Tomorrow eligibility; app orchestration determines data-dependent Daily membership and the actual batch plan.
`Lookup`, `Resolve`, and report-name helpers prevent callers from duplicating
report identity rules. Registry overrides clone a definition and replace its
module list only after the report ID is recognized.
The definition's `DistributorPathTemplates` are internal declarations consumed The registry never collects weather data, parses CLI flags, writes output, executes Promptkit, or delivers a report.
by app orchestration. Their rendered external bundle paths and compatibility
contract are documented in the [Distributor bundle guide](../integrations/distributor/pkg-bundle.md), not repeated here.
`morning` and `evening` are registry-owned batch names. Registry flags declare Focused tests cover definition completeness, command and alias lookup, period resolution, run IDs, output names, composition defaults, and override validation:
fixed report eligibility; app orchestration determines data-dependent Daily
membership and produces the actual batch plan.
## Module composition and failures
Each definition supplies an ordered `[]module.ConfigItem`; the complete
report-to-module mapping is maintained in [module internals](module.md).
`ArtifactGroup`, `BatchOutputName`, and comparison compatibility
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
Promptkit, or delivers a report.
## Verification and invariants
Focused tests cover definition completeness, command and alias lookup, period
resolution, run IDs, path declarations, composition defaults, and override
validation:
```sh ```sh
go test ./internal/report go test ./internal/report
``` ```
All report selection goes through the registry, and the registry is the source
of truth for report identity—not rendered report text or app-local constants.

View File

@@ -1,58 +0,0 @@
# State Internals
`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.
## Artifact Paths
For each run, paths are grouped by artifact group and valid start date:
| Artifact | Location |
| --- | --- |
| Module snapshot | `snapshots/<group>/<date>/modules.<run-id>.json` |
| Metadata | `snapshots/<group>/<date>/metadata.<run-id>.json` |
| Data package | `data-packages/<group>/<date>/data_package.<run-id>.yaml` |
| Prompt preparation | `preflight/<group>/<date>/prompt_preparation.<run-id>.json` |
| Prompt execution | `snapshots/<group>/<date>/prompt_execution.<run-id>.json` |
| Raw generated text | `snapshots/<group>/<date>/generated_text_raw.<run-id>.json` |
| Validated generated text | `snapshots/<group>/<date>/generated_text.<run-id>.json` |
| Render context | `snapshots/<group>/<date>/render_context.<run-id>.json` |
| Managed report | `reports/<group>/<date>/report.<run-id>.md` |
| Notification | `notifications/<group>/<date>/distributor.<run-id>.json` |
Batch notification records are `notifications/batches/<batch>/<local-date>/distributor.<batch-run-id>.json`.
## Metadata And Debug Storage
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.
Prompt preparation and execution records are validated on both save and load.
They require exact report/prompt identity, complete timing, internally
consistent provenance, and status-appropriate validation or bounded classified
errors. Completed preparation and execution provenance retain the selected
logical profile ID and resolved backend/model, but never profile endpoints or
credentials. Completed execution provenance keeps Promptkit's run identity
distinct from the Weatherreporter run identity.
For a completed prompt run, the execution record is atomically replaced after
each downstream artifact is saved. Its path set therefore records the raw and
normalized generated text, render context, managed report, requested output
copy, and notification artifact actually reached without changing the original
Promptkit outcome.
`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
`<root>/<report-id>/<valid-date>/<run-id>/`. Directories are `0700`; files are
atomic `0600`. Normal state discovery does not read this root.
Focused checks:
```sh
go test ./internal/state
```

View File

@@ -1,7 +1,7 @@
# Weather Data Internals # Weather Data Internals
`internal/weatherdata` owns the normalized, wire-independent weather bundle `internal/weatherdata` owns the normalized, wire-independent weather bundle
that passes from collection through rendering and persistence. The Weather API that passes from collection through rendering. The Weather API
adapter translates provider responses into these types; its request, response, adapter translates provider responses into these types; its request, response,
and availability contract is documented in the and availability contract is documented in the
[Weather API integration guide](../integrations/weatherapi.md). [Weather API integration guide](../integrations/weatherapi.md).
@@ -54,8 +54,7 @@ local provenance and whole-run consumers see it. A policy that treats a missing
source as an error returns no partial bundle. source as an error returns no partial bundle.
Warnings describe data completeness, not rendering or delivery failures. Warnings describe data completeness, not rendering or delivery failures.
Those failures are recorded by the application and state layers; see Those failures are reported by [application orchestration](app-orchestration.md).
[application orchestration](app-orchestration.md) and [state internals](state.md).
## Boundaries and verification ## Boundaries and verification