Implemented debug artifacts for the distributor notification adapter

This commit is contained in:
2026-06-07 20:21:26 -05:00
parent 138bc4e7e4
commit 183b23cf5a
18 changed files with 601 additions and 77 deletions

View File

@@ -134,6 +134,7 @@ stub source slots use the missing-source policy.
- `reports_dir`: managed Markdown report directory under `workspace.root`. Default: `reports`.
- `data_packages_dir`: prompt input package directory under `workspace.root`. Default: `data-packages`.
- `preflight_dir`: Scriptorium render output directory under `workspace.root`. Default: `preflight`.
- `notifications_dir`: distributor notification debug artifact directory under `workspace.root`. Default: `notifications`.
Workspace subdirectories must be relative paths that stay inside
`workspace.root`.

View File

@@ -81,12 +81,17 @@ Single-report generation follows this order:
14. Save metadata with the managed report path.
15. If distributor notification is enabled, notify using the managed report
path as the source file.
16. Save a distributor notification debug artifact and update metadata with its
path.
If render preflight returns both a result and an error, preflight JSON and
metadata are persisted before the error is returned. If Scriptorium report
generation returns an error after writing output, the managed report and
metadata remain inspectable. Notification is not attempted after Weather API,
briefing, prompt input, render, Scriptorium run, or metadata-save failures.
When notification is attempted, the debug artifact records request identity,
accepted upload fields, distributor status fields, raw status report JSON when
available, and redacted failure context.
`--out` copies are never used as notification source files.
## Batch Workflow

View File

@@ -8,7 +8,8 @@ This document describes the distributor upload adapter in
The adapter submits generated weatherreporter Markdown reports to a configured
distributor HTTP upload endpoint. It isolates distributor package types,
token-env lookup, upload client construction, source-bundle file mapping,
timeout handling, and upload error wrapping from app orchestration.
timeout handling, status polling, and upload error wrapping from app
orchestration.
## Inputs And Outputs
@@ -21,12 +22,14 @@ Inputs:
- idempotency key
- source Markdown report path
- bundle-relative Markdown path
- bundle created timestamp
- context for cancellation
Outputs:
- accepted distributor run ID
- accepted distributor status
- accepted distributor upload status
- distributor run status, status polling error, and raw run report JSON when available
- weatherreporter-owned idempotency conflict error when applicable
## Boundaries
@@ -66,11 +69,21 @@ The adapter calls distributor `UploadFiles` with exactly one file:
- source path: the managed Markdown report path selected by app orchestration
- bundle path: the rendered bundle-relative report path
- created: the report generation timestamp
The adapter creates a distributor upload client with the configured endpoint,
bearer token, and timeout-backed HTTP client. It also wraps the upload context
with the configured timeout when the timeout is greater than zero.
After upload acceptance, the adapter polls distributor `Status` for the accepted
run ID until the run reaches `succeeded` or `failed`, or until the configured
timeout expires. It returns the latest status, error text, and raw report JSON in
weatherreporter-owned types so app orchestration can persist them in the
notification debug artifact. Status lookup failures or timeout before a terminal
state are kept as debug status errors on an otherwise accepted upload. A
terminal distributor run status of `failed` is returned as a notification failure
with the status report preserved.
## Failure Behavior
The adapter validates required endpoint, token env name, token value, bundle ID,

View File

@@ -47,6 +47,7 @@ converts adapter render results into that shape before saving.
- `workspace.reports_dir`
- `workspace.data_packages_dir`
- `workspace.preflight_dir`
- `workspace.notifications_dir`
Workspace subdirectories must be relative paths that stay under
`workspace.root`.
@@ -62,12 +63,14 @@ valid-period start date for JSON artifacts, and the RunID.
snapshots/<artifact_group>/<YYYY-MM-DD>/<run_id>.metadata.json
data-packages/<artifact_group>/<YYYY-MM-DD>/<run_id>.data_package.json
preflight/<artifact_group>/<YYYY-MM-DD>/<run_id>.render.json
notifications/<artifact_group>/<YYYY-MM-DD>/<run_id>.distributor.json
reports/<artifact_group>/<run_id>.md
```
Metadata is stored beside briefing snapshots and links the briefing, data
package, preflight, report paths, and configured prompt location. Report
listing walks metadata files under the snapshots directory.
package, preflight, report paths, notification path when attempted, and
configured prompt location. Report listing walks metadata files under the
snapshots directory.
## Prior Lookup
@@ -89,6 +92,8 @@ current report definition.
Durable JSON writes use shared atomic file helpers. Managed Markdown reports are
prepared by creating their parent directory; Scriptorium writes the report body
to the prepared path. Extra Markdown copies are handled by app orchestration.
Distributor notification debug artifacts are written atomically when
notification is attempted.
Inspection helpers read existing metadata, briefing, and data package files.
Missing metadata directories return no inspection records or no prior snapshot

View File

@@ -91,6 +91,19 @@ workspace/
storm/
YYYY-MM-DD/
<run_id>.render.json
notifications/
daily/
YYYY-MM-DD/
<run_id>.distributor.json
three-day/
YYYY-MM-DD/
<run_id>.distributor.json
weekend/
YYYY-MM-DD/
<run_id>.distributor.json
storm/
YYYY-MM-DD/
<run_id>.distributor.json
reports/
daily/
<run_id>.md
@@ -122,6 +135,7 @@ Each generated report writes metadata that links:
- prompt input data package path
- preflight output path
- managed Markdown report path
- distributor notification debug artifact path, when notification is attempted
Batch summaries include report status, error text when applicable, notification
outcome when attempted, valid period, and known artifact paths for each
@@ -153,6 +167,16 @@ not trigger notification. A notification failure fails that report. In a batch,
other reports continue, the failed report includes notification fields in the
JSON summary, and the batch returns nonzero.
Each notification attempt writes a debug artifact under `notifications/`. The
artifact records the rendered bundle ID, idempotency key, managed source path,
bundle-relative path, bundle created timestamp, accepted upload response, and
the latest distributor run status response when available. Weatherreporter polls
status until distributor reports `succeeded` or `failed`, or until the configured
notification timeout expires. The run status includes the distributor status,
error text, and raw run report JSON, which can show actions such as
`replace_older`, `skip_same`, `skip_destination_newer`, or `failed`. Token values
are not written.
Weatherreporter is responsible for selecting the managed Markdown report,
constructing a source bundle, and submitting it to the configured distributor
HTTP endpoint. Distributor remains responsible for destination routing,

View File

@@ -248,6 +248,10 @@ Diagnostic: inspect the failed batch JSON or stderr line for bundle and
idempotency context. Compare the configured templates with the report RunID and
report path.
Also inspect the notification artifact linked from metadata. It records the
rendered bundle ID, idempotency key, upload result, distributor run status,
status error, and raw run report JSON when available.
Safe fix: keep idempotency templates stable for retries of the same generated
report, but do not reuse the same rendered key for different generated report
content.
@@ -268,6 +272,11 @@ Diagnostic: inspect stdout JSON or stderr status lines for
`notify.distributor.report_path_template`, and token configuration. Token values
are redacted from weatherreporter errors.
If the upload was accepted but destination output did not change, inspect the
notification artifact's `runStatus.report`. Distributor actions such as
`replace_older`, `skip_same`, `skip_destination_newer`, or `failed` explain how
the destination handled the uploaded bundle.
Safe fix: fix the endpoint, token, templates, or distributor-side upload
configuration. The weatherreporter upload source is the managed Markdown report,
not `--out` or `--out-dir` copies.