Complete stateless execution remediation

This commit is contained in:
2026-08-01 22:01:28 +00:00
parent 8d6ab0eb56
commit ab9218b124
7 changed files with 68 additions and 58 deletions

3
.gitignore vendored
View File

@@ -1,6 +1,5 @@
# Compiled application binary and testing workspace
# Compiled application binary
/weatherreporter
/workspace
# ---> Go
# If you prefer the allow list template instead of the deny list, see community template:

View File

@@ -99,6 +99,9 @@ its identity, status, effective profile and model details when available,
source warnings, validation status, and absolute `outputPath` after publication.
The top-level summary may also contain a batch `notification` object and
`error`. Batch status is `failed` if any report or the batch notification fails.
The `total`, `succeeded`, and `failed` counters describe report items only, so
a failed batch notification can leave `failed` at `0` while the top-level
notification and action status are `failed`.
Without `--quiet`, batch status lines use this form:

View File

@@ -8,13 +8,13 @@
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.
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.
Failures return an active partial result with safe identity, profile, warning, validation, debug, and output information when available. After rendering and immediately before publication, the workflow checks for cancellation or deadline expiry. Any failure before publication leaves an existing destination unchanged. A notification failure retains the newly published output.
## Batches
`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.
`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, then validates and retains the final output path for every planned report before invoking the same generation core sequentially.
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.
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. Batch result counters count report items only; a batch notification failure is represented by the top-level notification result and still produces a failed batch outcome.
## Boundaries And Verification

View File

@@ -40,8 +40,12 @@ Without `--out-dir`, batch reports are written beneath the current directory.
Morning runs Today, Tomorrow, and every eligible dated Daily Report; evening
runs Tomorrow and the same eligible Daily Reports. Eligible Daily dates begin
after tomorrow and require complete hourly coverage for their local civil day.
A batch collects once, processes each selected report independently, and keeps
successful outputs if another report fails.
A batch collects once, determines the complete report set, and validates every
final output destination before executing its first report prompt. A destination
collision, such as a directory named `tomorrow.md`, stops the batch before any
report output is created or replaced. After successful validation, each selected
report processes independently and successful outputs remain available if
another report fails.
When `notify.distributor.enabled` and batch notification are enabled,
Weatherreporter sends one Distributor upload only after every selected output
@@ -50,6 +54,9 @@ files remain at their selected destinations. A batch notification failure also
leaves all successfully published report files in place. Distributor source
files are those operator-owned Markdown outputs; rendered bundle paths and
delivery status appear in the result, not in a local notification receipt.
Report counters count report items only. A batch notification failure therefore
returns a failed batch status even when all report counters show success; the
top-level notification result contains the delivery diagnostic.
For a single report, Distributor notification follows the atomic output write.
See the [configuration reference](config.md) for pipeline, bundle,

View File

@@ -17,9 +17,10 @@ uploaded through Distributor.
The supported report products are Daily, Today, Tomorrow, and Hourly. A batch
collects once, validates its complete candidate prompt/profile set before
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.
collection, then determines and validates every planned output destination
before executing reports sequentially with one executor. It continues after
independent report failures and sends a batch notification only after every
planned report succeeds.
## Ownership And Boundaries
@@ -58,11 +59,14 @@ directly.
text, and render context in memory and creates no application-owned durable
state.
- Markdown writes are atomic at an operator-selected destination. A
pre-publication failure does not replace an existing destination; a
notification failure does not remove a newly published output.
pre-publication failure, including cancellation observed immediately before
publication, does not replace an existing destination; a notification failure
does not remove a newly published output.
- Distributor uploads use only the published Markdown output, never a scan of
local files. Single notification follows publication; batch notification
follows publication of every selected report.
follows publication of every selected report. Batch counters describe report
outcomes only; a failed batch notification is represented separately at the
batch level.
- Default tests are deterministic, offline, and use Promptkit/provider fakes
rather than live provider calls. See the [testing policy](testing.md).

View File

@@ -34,24 +34,24 @@ The target design reflects these product expectations:
- sensitive diagnostics are retained only through an explicit,
operator-controlled debug option.
## Current State
## Former State
Each generation currently writes a run-addressed collection containing a
Before the stateless implementation, each generation wrote a run-addressed collection containing a
module snapshot, data package, prompt preparation receipt, prompt execution
receipt, raw generated text, validated generated text, render context, managed
report, metadata, and optional notification receipt. Successful and failed
runs accumulate beneath the configured workspace.
runs accumulated beneath the configured workspace.
Metadata links these artifacts and supports lookup by RunID. The CLI can list
Metadata linked these artifacts and supported lookup by RunID. The CLI could list
historical runs and inspect their metadata, modules, data packages, prior
snapshots, and source provenance. The reader retains V1 compatibility while
new runs write V2 metadata.
snapshots, and source provenance. The reader retained V1 compatibility while
new runs wrote V2 metadata.
Weatherreporter also loads a compatible prior module snapshot for Daily,
Today, and Tomorrow and compares it with the current snapshot. Configurable
thresholds determine whether structured Recent Changes are included in the
Promptkit data package. This is the only current product behavior that depends
on state from an earlier invocation.
Weatherreporter also loaded a compatible prior module snapshot for Daily,
Today, and Tomorrow and compared it with the current snapshot. Configurable
thresholds determined whether structured Recent Changes were included in the
Promptkit data package. This was the only product behavior that depended on
state from an earlier invocation.
## Desired End State
@@ -130,9 +130,9 @@ information rather than retained Weatherreporter history.
## Recent Changes Deprecation And Removal
The local Recent Changes feature is deprecated by this accepted direction and
is removed when the stateless execution change lands. Its low practical value
does not justify retaining a historical state subsystem.
The local Recent Changes feature was deprecated by this accepted direction and
removed when the stateless execution change landed. Its low practical value did
not justify retaining a historical state subsystem.
Removal includes:
@@ -145,12 +145,11 @@ Removal includes:
- the `recent_changes` Promptkit data-package stanza; and
- prompt instructions that refer to supplied recent changes.
Removing the prompt-input field is a breaking prompt contract change. The data
package schema advances from `weatherreporter.data_package.v3` to
`weatherreporter.data_package.v4`, and all four prompt definitions advance from
version `1.1.0` to `2.0.0` together.
Generated-text schemas and report templates do not change; neither has a
direct dependency on Recent Changes.
Removing the prompt-input field was a breaking prompt contract change. The data
package schema advanced from `weatherreporter.data_package.v3` to
`weatherreporter.data_package.v4`, and all four prompt definitions advanced
from version `1.1.0` to `2.0.0` together. Generated-text schemas and report
templates did not change; neither had a direct dependency on Recent Changes.
Weatherreporter does not retain an empty compatibility field and does not keep
a local fallback comparator. Reports simply omit change commentary after this
@@ -181,7 +180,7 @@ capture contract incidentally.
## Removed State And Inspection Contracts
The target removes:
The implementation removed:
- the `workspace` configuration section and its directory settings;
- durable module snapshots, data packages, preparation and execution receipts,
@@ -197,36 +196,36 @@ No replacement inspection command or current-state manifest is introduced.
The active action summary, final output, command error, and opt-in debug capture
are the supported diagnostic surfaces.
State-independent atomic file helpers may remain outside a state abstraction.
The target architecture should not preserve `internal/state` merely as a
compatibility wrapper after its state responsibilities disappear.
State-independent atomic file helpers remain outside a state abstraction. The
implemented architecture does not preserve `internal/state` merely as a
compatibility wrapper after its state responsibilities disappeared.
## Compatibility And Upgrade Policy
This is an intentional breaking change to the CLI, configuration, prompt-input,
This was an intentional breaking change to the CLI, configuration, prompt-input,
workspace, and inspection contracts. Weatherreporter does not migrate old V1
or V2 metadata or other historical artifacts.
Legacy workspace trees are ignored. Weatherreporter must not discover,
interpret, or automatically delete them. Release notes and operations
documentation identify the obsolete configuration and commands and provide a
precise manual cleanup procedure for operators who want to remove the legacy
workspace.
Legacy workspace trees are no longer ignored by the repository. Weatherreporter
must not discover, interpret, or automatically delete them. Release notes and
operations documentation should identify the obsolete configuration and
commands and provide a precise manual cleanup procedure for operators who want
to remove the legacy workspace.
Existing report files explicitly written through `--out` or `--out-dir` remain
operator-owned and are never treated as legacy workspace material.
The change should land in a release whose notes identify the removed Recent
Any release containing this implementation should identify the removed Recent
Changes behavior, configuration fields, inspection commands, artifact paths,
and metadata compatibility; the new default output destinations; and any
operator action required during upgrade.
## Required Architecture Decision Record
The target state includes an Accepted ADR recording the durable decision to
The implemented state includes an Accepted ADR recording the durable decision to
make Weatherreporter stateless.
The ADR should record:
The ADR records:
- the mismatch between run-addressed provenance storage and ephemeral weather
reports;
@@ -305,7 +304,7 @@ private replacement mechanics.
## Completion Criteria
The target state is achieved when:
The implemented state has these properties:
- a clean invocation requires no prior Weatherreporter-created files;
- ordinary runs leave only their selected Markdown outputs;

View File

@@ -1,18 +1,16 @@
# Stateless Execution Implementation Plan
Status: Ready for remediation implementation (Stages 14-18).
Status: Complete.
## Purpose
This plan implements the accepted [Stateless Execution
Roadmap](ephemeral-state.md). The roadmap is authoritative for product intent,
policy choices, and the desired end state. This document records the completed
migration and defines the remaining remediation work discovered during
post-implementation review.
migration and records the remediation work completed during post-implementation
review.
Stages 1-13 are complete and are summarized below. Implement Stages 14-18 in
numeric order. Each remaining stage is intentionally scoped for one focused
implementation prompt.
Stages 1-18 are complete and are summarized below.
## Implementation Rules
@@ -130,7 +128,7 @@ historical inspection.
Ran the complete offline test, race, vet, build, help, formatting, stale-string,
and documentation review gates and marked the initial migration implemented.
## Stage 14: Prevent Publication After Cancellation
## Stage 14: Prevent Publication After Cancellation — Complete
### Goal
@@ -174,7 +172,7 @@ git diff --check
Cancellation observable before publication prevents the atomic write, the
selected destination remains unchanged, and cancellation identity is retained.
## Stage 15: Preflight Every Planned Batch Output
## Stage 15: Preflight Every Planned Batch Output — Complete
### Goal
@@ -222,7 +220,7 @@ git diff --check
Every selected batch destination is validated before any batch report executes,
and a destination collision cannot yield an unreported partial batch.
## Stage 16: Separate Report Counts From Batch Notification Status
## Stage 16: Separate Report Counts From Batch Notification Status — Complete
### Goal
@@ -273,7 +271,7 @@ Batch report counters are internally consistent, while notification failure
still produces a failed summary, safe diagnostic, retained outputs, and
non-zero command result.
## Stage 17: Remove Impossible Per-Report Notification State
## Stage 17: Remove Impossible Per-Report Notification State — Complete
### Goal
@@ -314,7 +312,7 @@ git diff --check
Batch items expose only report-generation facts, and all batch delivery state
is represented by the single top-level notification result.
## Stage 18: Reconcile Documentation And Run The Remediation Exit Gate
## Stage 18: Reconcile Documentation And Run The Remediation Exit Gate — Complete
### Goal