326 lines
15 KiB
Markdown
326 lines
15 KiB
Markdown
# Stateless Execution Roadmap
|
|
|
|
Status: Accepted.
|
|
|
|
## Purpose
|
|
|
|
Weatherreporter should be a stateless report transformation pipeline. Each
|
|
invocation fetches current inputs from the Weather API, derives deterministic
|
|
facts, executes Promptkit, renders Markdown, and writes or distributes the
|
|
completed report. It does not retain application-owned history or operational
|
|
state between invocations.
|
|
|
|
Weather reports are ephemeral products rather than business records. Forecasts
|
|
and current conditions change continuously, and the normal response to an old
|
|
or failed report is to generate a new one rather than recover, replay, or
|
|
inspect the prior generation.
|
|
|
|
This roadmap defines the desired lifecycle, output contract, compatibility
|
|
policy, and architectural boundaries.
|
|
|
|
## User Intent
|
|
|
|
The target design reflects these product expectations:
|
|
|
|
- each invocation is independent and requires no prior Weatherreporter state;
|
|
- routine operation creates only the requested report outputs;
|
|
- reports are written somewhere useful even when the operator omits an
|
|
explicit output flag;
|
|
- Weatherreporter does not maintain forecast history merely to compare runs;
|
|
- regenerating replaces a same-named output atomically instead of creating an
|
|
archive;
|
|
- Distributor receives the completed report produced by the current
|
|
invocation; and
|
|
- sensitive diagnostics are retained only through an explicit,
|
|
operator-controlled debug option.
|
|
|
|
## Current State
|
|
|
|
Each generation currently writes 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.
|
|
|
|
Metadata links these artifacts and supports lookup by RunID. The CLI can 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.
|
|
|
|
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.
|
|
|
|
## Desired End State
|
|
|
|
Weatherreporter has no durable application-managed workspace. Its dataflow is:
|
|
|
|
```text
|
|
Weather API input
|
|
-> deterministic facts and modules
|
|
-> Promptkit data package and generated text
|
|
-> repository-owned Markdown rendering
|
|
-> operator-owned report output
|
|
-> optional Distributor upload
|
|
```
|
|
|
|
Intermediate values remain in memory wherever practical. A narrowly scoped
|
|
temporary file may be used when an external interface requires a file path,
|
|
but it exists only for the active invocation and is removed on return.
|
|
Temporary material is not a supported recovery or inspection surface.
|
|
|
|
RunIDs may remain as in-process correlation identifiers in action summaries,
|
|
errors, Distributor idempotency values, and explicit debug paths. They do not
|
|
identify a collection that Weatherreporter can locate or decode later.
|
|
|
|
Configuration files, operator-owned report outputs, and explicitly requested
|
|
debug captures are inputs or outputs, not Weatherreporter state.
|
|
|
|
## Report Output Contract
|
|
|
|
Every successful report generation writes one operator-owned Markdown output.
|
|
An explicit output option selects its destination. When no explicit destination
|
|
is supplied, Weatherreporter uses the process working directory captured at
|
|
invocation start.
|
|
|
|
Default single-report filenames are:
|
|
|
|
| Report | Default output |
|
|
| --- | --- |
|
|
| Daily | `daily-YYYY-MM-DD.md`, using the report's valid local date |
|
|
| Today | `today.md` |
|
|
| Tomorrow | `tomorrow.md` |
|
|
| Hourly | `hourly.md` |
|
|
|
|
`--out PATH` replaces the default destination for `generate`; it no longer
|
|
means an extra copy of a separately managed report. Relative paths are resolved
|
|
from the invocation's working directory.
|
|
|
|
For `run`, `--out-dir PATH` selects the report-output directory and the current
|
|
working directory is the default when it is omitted. Existing batch filenames
|
|
remain: `today.md`, `tomorrow.md`, and `daily-YYYY-MM-DD.md`. Successful items
|
|
in a partially failed batch retain their outputs.
|
|
|
|
Output publication is atomic. A completed generation may atomically replace an
|
|
existing file at the selected path, but a failed or canceled generation must
|
|
not truncate or partially replace it. Weatherreporter does not rotate, archive,
|
|
expire, or otherwise manage an output after publication.
|
|
|
|
The JSON action summary reports the final output path. It does not expose paths
|
|
to transient intermediates. `--quiet` continues to suppress the action summary,
|
|
not report creation.
|
|
|
|
## Distributor Contract
|
|
|
|
Distributor uploads use the completed Markdown output from the active
|
|
invocation. There is no separate durable managed-report copy and no workspace
|
|
scan.
|
|
|
|
For a single report, local output publication completes before notification.
|
|
A notification failure leaves the report output intact and returns a safe
|
|
error through the active result. It does not create a notification receipt.
|
|
|
|
Batches continue to suppress per-report notification and attempt their
|
|
batch-level upload only after every planned report succeeds. A report failure
|
|
leaves other successful output files intact, skips the batch upload, and
|
|
returns an aggregate failure. Distributor status remains active-workflow
|
|
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.
|
|
|
|
Removal includes:
|
|
|
|
- prior-snapshot discovery and compatibility rules;
|
|
- the `internal/changes` comparison implementation;
|
|
- report-registry comparison strategies and compatible-prior declarations;
|
|
- `recent_change` configuration and threshold validation;
|
|
- Recent Changes values in application results, prompt inputs, fixtures, and
|
|
tests;
|
|
- 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.
|
|
|
|
Weatherreporter does not retain an empty compatibility field and does not keep
|
|
a local fallback comparator. Reports simply omit change commentary after this
|
|
feature is removed.
|
|
|
|
A future upstream Weather API change product may allow Weatherreporter to
|
|
reintroduce structured change commentary without local state. That work is
|
|
recorded in [Future Roadmap](future.md#upstream-forecast-change-product) and is
|
|
not a prerequisite for this refactor.
|
|
|
|
## Debugging
|
|
|
|
Prompt inspection before weather collection and prepared execution remain
|
|
runtime safety requirements. Preparation details, effective profile and model,
|
|
validation outcomes, source warnings, and safe errors remain available to the
|
|
active workflow and its action summary where useful.
|
|
|
|
The existing `--llm-debug-dir PATH` option remains the explicit exception to
|
|
stateless output. When supplied, it may retain rendered prompts, schemas, input
|
|
bodies, generated bodies, and effective parameters according to its secure
|
|
capture contract. The operator selects and manages that location;
|
|
Weatherreporter does not clean or archive it. Credentials remain excluded.
|
|
|
|
Adding a broader logging framework or an implicit persistent debug directory
|
|
is outside this feature. A future rename or generalization to `--debug` should
|
|
be considered separately so this state refactor does not expand the sensitive
|
|
capture contract incidentally.
|
|
|
|
## Removed State And Inspection Contracts
|
|
|
|
The target removes:
|
|
|
|
- the `workspace` configuration section and its directory settings;
|
|
- durable module snapshots, data packages, preparation and execution receipts,
|
|
raw and validated generated text, render contexts, run metadata, managed
|
|
reports, and notification receipts;
|
|
- historical artifact path fields from action results and summaries;
|
|
- V1 and V2 metadata models, readers, validators, and compatibility behavior;
|
|
- state lookup, prior selection, and run-history discovery; and
|
|
- `inspect reports`, `inspect metadata`, `inspect modules`,
|
|
`inspect data-package`, `inspect prior`, and `inspect sources`.
|
|
|
|
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.
|
|
|
|
## Compatibility And Upgrade Policy
|
|
|
|
This is 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.
|
|
|
|
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
|
|
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
|
|
make Weatherreporter stateless.
|
|
|
|
The ADR should record:
|
|
|
|
- the mismatch between run-addressed provenance storage and ephemeral weather
|
|
reports;
|
|
- the decision to remove local change detection rather than retain state for a
|
|
rarely used report section;
|
|
- the transformation-pipeline model and operator-owned output boundary;
|
|
- the absence of historical inspection and backward-compatibility guarantees;
|
|
- atomic output and failure behavior;
|
|
- the separation of explicit debug capture from ordinary execution;
|
|
- the upstream-service path for any future forecast comparison; and
|
|
- alternatives considered, including the former bounded-current-state design,
|
|
time-based retention, and a bounded run history.
|
|
|
|
Once accepted, the ADR owns the rationale. Architecture owns the resulting
|
|
stateless invariant, while CLI, operations, configuration, integrations, and
|
|
focused internal documents own implemented contracts.
|
|
|
|
## Scope
|
|
|
|
The completed feature includes:
|
|
|
|
- removal of local Recent Changes and all prior-run dependencies;
|
|
- removal of the durable workspace, artifact persistence, metadata
|
|
compatibility, and historical inspection surfaces;
|
|
- in-memory or invocation-temporary processing with safe cleanup;
|
|
- atomic operator-owned output for every successful report;
|
|
- current-working-directory defaults and explicit output overrides;
|
|
- preservation of report generation, batch membership, Promptkit execution,
|
|
Distributor delivery, action summaries, and opt-in secure debug capture;
|
|
- removal or simplification of state-only packages, fields, configuration,
|
|
fixtures, tests, and documentation;
|
|
- exact-version prompt updates for the breaking input-contract change;
|
|
- deterministic offline tests for output atomicity, failure isolation, default
|
|
path selection, Distributor sequencing, and absence of durable state;
|
|
- an Accepted ADR documenting the decision; and
|
|
- canonical documentation describing the implemented contract and clear
|
|
release-note requirements for the release that publishes it.
|
|
|
|
## Non-Goals
|
|
|
|
This feature does not include:
|
|
|
|
- the future upstream forecast-change API or reintroduced change commentary;
|
|
- a cache, database, archive, retention engine, manifest, or resume mechanism;
|
|
- migration or automatic deletion of legacy workspace artifacts;
|
|
- retaining a bounded report or snapshot history;
|
|
- changing weather derivation, report periods, report membership, generated
|
|
prose schemas, profile selection, or the provider model ladder;
|
|
- changing Distributor's remote API or bundle-content contract;
|
|
- deleting or managing operator-owned report and debug outputs;
|
|
- a general logging or observability subsystem; or
|
|
- live external services in the default test suite.
|
|
|
|
## Safety And Testing Policy
|
|
|
|
Tests should emphasize observable stateless behavior rather than removed file
|
|
choreography. Important risks requiring durable offline coverage include:
|
|
|
|
- a failed or canceled generation truncating or replacing an existing output;
|
|
- default paths resolving somewhere other than the invocation working
|
|
directory;
|
|
- Daily output using the wrong valid local date;
|
|
- a batch item overwriting another planned output;
|
|
- a notification attempt occurring before its report output is complete;
|
|
- one batch failure deleting or corrupting another report's successful output;
|
|
- summaries exposing nonexistent transient paths;
|
|
- temporary files surviving an ordinary success or handled failure;
|
|
- default operation recreating a workspace or historical artifact tree; and
|
|
- debug capture leaking credentials or being created without explicit opt-in.
|
|
|
|
Tests remain deterministic, offline, credential-free, and use real temporary
|
|
directories plus narrow external-boundary fakes. Existing tests whose only
|
|
purpose is to preserve removed state, metadata, inspection, or Recent Changes
|
|
contracts should be deleted rather than translated into assertions about
|
|
private replacement mechanics.
|
|
|
|
## Completion Criteria
|
|
|
|
The target state is achieved when:
|
|
|
|
- a clean invocation requires no prior Weatherreporter-created files;
|
|
- ordinary runs leave only their selected Markdown outputs;
|
|
- omitted output flags resolve to the documented filenames in the current
|
|
working directory;
|
|
- failed and canceled attempts preserve any existing destination file;
|
|
- no local prior-run comparison or Recent Changes contract remains;
|
|
- no workspace configuration, run-history command, metadata compatibility, or
|
|
durable intermediate-artifact contract remains;
|
|
- Distributor uses only completed current-invocation outputs;
|
|
- debug files are created only through explicit secure capture;
|
|
- repeated successful and failed runs do not create application-owned history;
|
|
- the test suite proves the stateless, atomic-output, batch, notification, and
|
|
security boundaries offline;
|
|
- an Accepted ADR records the architectural decision; and
|
|
- canonical current-state documentation describes only the implemented
|
|
stateless lifecycle.
|