Plan the stateless execution refactor
This commit is contained in:
@@ -1,39 +1,38 @@
|
||||
# Ephemeral Operational State Roadmap
|
||||
# Stateless Execution Roadmap
|
||||
|
||||
Status: Accepted feature direction; implementation has not started.
|
||||
Status: Accepted.
|
||||
|
||||
## Purpose
|
||||
|
||||
Weatherreporter should treat generated weather reports and their intermediate
|
||||
artifacts as short-lived operational material rather than a durable audit
|
||||
history. Forecasts and current conditions change continuously, and the normal
|
||||
response to an old or failed report is to generate a new report, not to
|
||||
reconstruct the provenance of the old one.
|
||||
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.
|
||||
|
||||
The application should retain only the bounded state needed to publish the
|
||||
current report, calculate Recent Changes against the last successfully
|
||||
published report for the same valid period, and complete the current
|
||||
invocation safely. Detailed LLM diagnostics should remain an explicit,
|
||||
operator-controlled exception outside ordinary workspace state.
|
||||
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 intended state lifecycle, compatibility policy, and
|
||||
architectural boundaries. A separate implementation plan will define the
|
||||
ordered work after the roadmap is complete.
|
||||
This roadmap defines the desired lifecycle, output contract, compatibility
|
||||
policy, and architectural boundaries.
|
||||
|
||||
## User Intent
|
||||
|
||||
The state model should reflect these product expectations:
|
||||
The target design reflects these product expectations:
|
||||
|
||||
- weather reports are ephemeral products, not business records;
|
||||
- old report provenance has no continuing operational value once conditions
|
||||
and forecasts have changed;
|
||||
- regenerating is preferable to recovering, replaying, or inspecting an old
|
||||
generation;
|
||||
- routine operation should not accumulate unbounded run-addressed artifacts;
|
||||
- Recent Changes remains useful, but needs only one prior successful snapshot
|
||||
for the same report and valid period; and
|
||||
- sensitive prompt and response capture remains opt-in and explicitly managed
|
||||
by the operator.
|
||||
- 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
|
||||
|
||||
@@ -41,337 +40,286 @@ 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 workspace.
|
||||
runs accumulate beneath the configured workspace.
|
||||
|
||||
Metadata links the collection and supports lookup by RunID. The CLI can list
|
||||
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. New metadata uses the V2 format while the
|
||||
reader retains V1 compatibility. Prompt artifacts are validated against
|
||||
current report and prompt definitions when saved and loaded.
|
||||
snapshots, and source provenance. The reader retains V1 compatibility while
|
||||
new runs write V2 metadata.
|
||||
|
||||
Most of this persistence exists for retrospective inspection and failure
|
||||
recovery. Dedicated prompt preparation and execution load operations have no
|
||||
ordinary production consumer. The important exception is module snapshot
|
||||
state: generation actively loads the most recent compatible snapshot to build
|
||||
the deterministic Recent Changes input for Daily, Today, and Tomorrow.
|
||||
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 three distinct state classes:
|
||||
Weatherreporter has no durable application-managed workspace. Its dataflow is:
|
||||
|
||||
| State class | Lifecycle | Purpose |
|
||||
| --- | --- | --- |
|
||||
| Invocation workspace | Temporary and unpublished | Hold intermediate values while one report or batch is running. |
|
||||
| Current published state | Bounded and replaceable | Hold the current managed report and the minimal deterministic snapshot or manifest needed for normal operation. |
|
||||
| Secure LLM debug capture | Explicitly enabled and operator-managed | Diagnose prompt rendering or provider output when the operator deliberately requests sensitive capture. |
|
||||
```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
|
||||
```
|
||||
|
||||
Ordinary generation uses an invocation-scoped temporary directory on the same
|
||||
filesystem as the managed workspace when atomic publication requires it.
|
||||
Prompt preparation, prompt execution, raw generated text, validated generated
|
||||
text, render contexts, data packages, and notification receipts may exist
|
||||
there while needed, but they are not published as durable historical
|
||||
artifacts.
|
||||
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.
|
||||
|
||||
A successful report atomically replaces the current published state for its
|
||||
logical report key and valid period. A failed attempt leaves the last
|
||||
successfully published report and comparison snapshot unchanged. Ordinary
|
||||
temporary artifacts are removed after both success and handled failure;
|
||||
cleanup failure is reported safely but must not replace the primary generation
|
||||
error.
|
||||
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.
|
||||
|
||||
RunIDs remain useful as in-process correlation identifiers in action results,
|
||||
logs, provider provenance, and optional debug paths. They no longer identify a
|
||||
durable collection that Weatherreporter promises to locate or decode later.
|
||||
Configuration files, operator-owned report outputs, and explicitly requested
|
||||
debug captures are inputs or outputs, not Weatherreporter state.
|
||||
|
||||
## Published Report Policy
|
||||
## Report Output Contract
|
||||
|
||||
The managed Markdown report remains the authoritative upload source during an
|
||||
invocation. The intended default is to retain only the current managed report
|
||||
for each logical report key and valid period, replacing it atomically after a
|
||||
new report has been fully rendered and validated.
|
||||
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.
|
||||
|
||||
An explicit `--out` or `--out-dir` copy remains operator-owned output outside
|
||||
the managed-state lifecycle. Weatherreporter does not delete, rotate, or
|
||||
rewrite those copies except when the same explicit destination is selected by
|
||||
a later invocation.
|
||||
Default single-report filenames are:
|
||||
|
||||
Distributor continues to receive only a completed managed Markdown report.
|
||||
Notification success or failure does not create a durable notification
|
||||
history. A notification failure leaves the newly published report available
|
||||
and returns a safe error through the current action result.
|
||||
| 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` |
|
||||
|
||||
## Recent Changes State
|
||||
`--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.
|
||||
|
||||
Recent Changes must be preserved without preserving general report history.
|
||||
For Daily, Today, and Tomorrow, Weatherreporter retains at most one compatible
|
||||
module snapshot for each logical report key and valid period.
|
||||
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.
|
||||
|
||||
The retained snapshot represents the last successfully published report. A
|
||||
new invocation reads it before constructing Recent Changes and replaces it
|
||||
only when the new managed report has been successfully validated, rendered,
|
||||
and published. A failed generation therefore does not become the baseline for
|
||||
the next report and cannot hide changes that the user has not yet seen.
|
||||
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.
|
||||
|
||||
Hourly does not currently use the comparison strategy and should not retain a
|
||||
comparison snapshot solely for symmetry. State whose valid period has ended
|
||||
and can no longer participate in a supported comparison is eligible for safe
|
||||
cleanup.
|
||||
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.
|
||||
|
||||
## Temporary Workspace And Failure Semantics
|
||||
## Distributor Contract
|
||||
|
||||
Temporary state must remain beneath a narrowly owned application directory and
|
||||
use safe path construction, restrictive permissions where content is
|
||||
sensitive, and atomic writes where practical. Publication must not expose a
|
||||
partially rendered report or a snapshot that does not correspond to the
|
||||
published report.
|
||||
Distributor uploads use the completed Markdown output from the active
|
||||
invocation. There is no separate durable managed-report copy and no workspace
|
||||
scan.
|
||||
|
||||
Normal results retain bounded error information and paths only for artifacts
|
||||
that remain meaningful after the command: a previously or newly published
|
||||
report, an explicit operator output, or an enabled secure debug capture.
|
||||
Temporary intermediate paths are not emitted as if they were durable recovery
|
||||
locations. A failed command is retried by starting a new generation.
|
||||
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.
|
||||
|
||||
Process interruption may leave an uncommitted temporary directory. Such a
|
||||
directory is never considered published state, is never selected for Recent
|
||||
Changes, and may be removed by a documented safe cleanup mechanism. Cleanup
|
||||
must distinguish inactive temporary directories from concurrent active
|
||||
invocations and must never recursively target the workspace root or an
|
||||
unresolved configuration path.
|
||||
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.
|
||||
|
||||
## Inspection And Metadata Policy
|
||||
## Recent Changes Deprecation And Removal
|
||||
|
||||
Run-history discovery and inspection are not part of the desired product
|
||||
contract. The historical `inspect reports`, `inspect metadata`, `inspect
|
||||
modules`, `inspect data-package`, `inspect prior`, and `inspect sources`
|
||||
surfaces are candidates for removal together rather than preservation through
|
||||
a new storage representation.
|
||||
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.
|
||||
|
||||
Any manifest retained for atomic publication or Recent Changes is current
|
||||
operational state, not an archival metadata record. It should contain only the
|
||||
identity, valid period, safe paths, and deterministic snapshot information
|
||||
needed to validate and use that current state. It does not need to preserve
|
||||
prompt messages, generated prose intermediates, source provenance, provider
|
||||
provenance, notification history, or a catalog of prior runs.
|
||||
Removal includes:
|
||||
|
||||
The application does not promise cross-version decoding of ordinary workspace
|
||||
state. A new release may replace or ignore incompatible current-state files,
|
||||
provided it fails safely, never mistakes stale state for a compatible Recent
|
||||
Changes baseline, and documents any operator action required during upgrade.
|
||||
- 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.
|
||||
|
||||
## Prompt Execution And Debugging
|
||||
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. They do not require durable preparation or
|
||||
execution receipts.
|
||||
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 selected logical profile, effective backend and model, validation outcome,
|
||||
and safe classified error remain available to the active workflow and its CLI
|
||||
summary where useful. Weatherreporter does not retain them as long-term report
|
||||
provenance after the invocation completes.
|
||||
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.
|
||||
|
||||
The existing explicit secure debug root remains outside ordinary state and may
|
||||
retain rendered prompts, schemas, input bodies, generated bodies, and effective
|
||||
parameters according to its documented contract. Weatherreporter does not
|
||||
automatically clean that operator-selected location. Credentials must remain
|
||||
excluded from debug capture.
|
||||
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 workspace and inspection
|
||||
contracts. Weatherreporter does not need to migrate historical V1 or V2
|
||||
metadata, prompt receipts, intermediate generated-text artifacts, or managed
|
||||
reports into the new representation.
|
||||
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 must not be silently interpreted as current published
|
||||
state. They also must not be deleted automatically merely because a new
|
||||
version starts: an operator may have placed or referenced files there despite
|
||||
the absence of a continuing application compatibility promise. Release notes
|
||||
and operations documentation must explain whether legacy data can be removed
|
||||
manually and identify the exact safe target.
|
||||
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.
|
||||
|
||||
The change should land in a release whose notes clearly identify removed CLI
|
||||
commands, obsolete paths and schemas, the new bounded state behavior, and any
|
||||
upgrade action. Because Weatherreporter remains pre-1.0, the ordinary semantic
|
||||
version policy may carry this breaking change without inventing a migration
|
||||
framework.
|
||||
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 implemented feature must include an Accepted ADR recording the durable
|
||||
architectural decision to use ephemeral operational state. The ADR is not part
|
||||
of this roadmap-writing pass and should not be created until implementation is
|
||||
being prepared.
|
||||
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 the ephemeral
|
||||
weather-report lifecycle;
|
||||
- the decision to retain bounded current report and comparison state rather
|
||||
than historical runs;
|
||||
- the distinction between temporary invocation state, published operational
|
||||
state, explicit output copies, and secure debug capture;
|
||||
- the removal of historical inspection and backward-compatibility guarantees;
|
||||
- atomic publication and failed-run behavior;
|
||||
- the alternatives considered, including retaining the current archive,
|
||||
adding time-based retention, or keeping a bounded run history; and
|
||||
- consequences for CLI compatibility, workspace layout, testing, operations,
|
||||
and future schema changes.
|
||||
- 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 decision rationale. The architecture policy
|
||||
owns the resulting current invariant, while focused state, CLI, operations,
|
||||
and integration documents own the implemented contracts.
|
||||
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:
|
||||
|
||||
- an invocation-scoped temporary workspace for intermediate generation state;
|
||||
- atomic publication of the current managed report and its minimal operational
|
||||
state;
|
||||
- a bounded comparison snapshot representing the last successfully published
|
||||
report for each supported report key and valid period;
|
||||
- safe cleanup behavior for normal completion, handled failure, and abandoned
|
||||
temporary workspaces;
|
||||
- removal of durable prompt preparation, prompt execution, generated-text,
|
||||
render-context, data-package, notification, and run-metadata history;
|
||||
- removal of run-history inspection commands and their application/state
|
||||
contracts;
|
||||
- removal of V1 metadata compatibility and current-version coupling for
|
||||
historical prompt artifacts by removing the historical artifact contract;
|
||||
- preservation of active-command partial status, safe errors, and paths to
|
||||
genuinely retained published, operator-owned, or debug outputs;
|
||||
- preservation of explicit output copies, Distributor upload behavior, and
|
||||
opt-in secure LLM debug capture;
|
||||
- risk-appropriate offline tests for atomic publication, comparison baselines,
|
||||
failure isolation, cleanup safety, concurrent invocation safety, and absence
|
||||
of unbounded state growth;
|
||||
- an Accepted ADR documenting the architectural decision; and
|
||||
- updates to canonical architecture, CLI, operations, configuration,
|
||||
integration, internal, testing, and release documentation
|
||||
where their contracts change.
|
||||
- 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:
|
||||
|
||||
- a general-purpose cache, database, archival service, or retention engine;
|
||||
- replaying or resuming interrupted generation;
|
||||
- migrating legacy artifacts into the new representation;
|
||||
- retaining a bounded number of historical runs for convenience;
|
||||
- automatic upload or archival of state to remote storage;
|
||||
- collecting additional provider telemetry or weather-source provenance;
|
||||
- changing report content, prompt text, schemas, profile selection, weather
|
||||
derivation, or batch membership;
|
||||
- deleting operator-owned `--out`, `--out-dir`, or secure debug files;
|
||||
- changing Distributor's report-content contract; or
|
||||
- making live external services part of the default test suite.
|
||||
- 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
|
||||
|
||||
The state refactoring must preserve Weatherreporter's existing path-safety and
|
||||
atomicity expectations while reducing the amount of durable state. Tests
|
||||
should emphasize observable lifecycle guarantees rather than private file
|
||||
choreography.
|
||||
Tests should emphasize observable stateless behavior rather than removed file
|
||||
choreography. Important risks requiring durable offline coverage include:
|
||||
|
||||
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.
|
||||
|
||||
- a failed or canceled generation replacing a previously published report or
|
||||
comparison baseline;
|
||||
- a partially written report becoming visible as current;
|
||||
- Recent Changes selecting an incompatible report, valid period, or failed
|
||||
attempt;
|
||||
- cleanup deleting published, operator-owned, debug, or concurrently active
|
||||
files;
|
||||
- batch partial success corrupting the state of another report;
|
||||
- notification failure rolling back or obscuring a successfully published
|
||||
report;
|
||||
- stale or incompatible current state being treated as valid; and
|
||||
- repeated successful and failed runs causing unbounded ordinary workspace
|
||||
growth.
|
||||
|
||||
Tests remain deterministic, offline, credential-free, and based on real
|
||||
temporary filesystems plus narrow external-boundary fakes. Race-enabled tests
|
||||
are required where publication, cleanup, or concurrent invocation behavior
|
||||
shares mutable filesystem state.
|
||||
|
||||
## Relationship To Domain-Specific Profiles
|
||||
|
||||
The implemented domain-specific profiles do not add historical compatibility
|
||||
or durable-provenance commitments. Profile inspection, selection, override
|
||||
precedence, and effective model resolution remain active-workflow behavior and
|
||||
survive the state change. Existing prompt artifacts need not remain readable
|
||||
after this refactor and must not constrain the target architecture.
|
||||
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 roadmap's target state is achieved when:
|
||||
The target state is achieved when:
|
||||
|
||||
- ordinary runs no longer create durable run-addressed artifact collections;
|
||||
- a successful report atomically replaces only the corresponding current
|
||||
published state;
|
||||
- failed and canceled attempts leave the prior published report and Recent
|
||||
Changes baseline unchanged;
|
||||
- Daily, Today, and Tomorrow compare against at most one compatible snapshot
|
||||
from the last successfully published report;
|
||||
- expired comparison and published state can be removed safely without
|
||||
touching operator-owned or active files;
|
||||
- Hourly does not retain an unused comparison snapshot;
|
||||
- historical inspection commands and V1/V2 archival compatibility code are
|
||||
removed;
|
||||
- temporary, published, explicit-output, and debug paths have distinct and
|
||||
documented ownership and cleanup rules;
|
||||
- Distributor and active-command summaries continue to receive the completed
|
||||
report and safe status information they require;
|
||||
- the default suite proves atomicity, bounded growth, cleanup safety, batch
|
||||
isolation, and comparison correctness offline;
|
||||
- an Accepted ADR records the architectural decision and alternatives; and
|
||||
- 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
|
||||
lifecycle.
|
||||
|
||||
## Open Questions
|
||||
|
||||
### Lifetime of the current managed report
|
||||
|
||||
Recommendation: retain one current managed report per logical report key and
|
||||
valid period until it is replaced or its valid period expires. This preserves
|
||||
the current default behavior for invocations without `--out` while bounding
|
||||
growth.
|
||||
|
||||
Alternative: treat the managed report as temporary and retain output only when
|
||||
the operator supplies `--out` or `--out-dir`. This minimizes state further but
|
||||
makes a successful default invocation produce no durable report for the user
|
||||
and complicates Distributor sequencing.
|
||||
|
||||
### Historical inspection replacement
|
||||
|
||||
Recommendation: remove the run-history inspection commands without adding a
|
||||
replacement initially. Current command summaries, current managed files, and
|
||||
opt-in debug capture cover the remaining supported workflows.
|
||||
|
||||
Alternative: add a narrow `inspect current REPORT` command backed only by the
|
||||
current operational manifest. This provides discoverability without history,
|
||||
but it creates a new public surface and may preserve metadata complexity that
|
||||
the refactor is intended to remove.
|
||||
|
||||
### Abandoned temporary workspace cleanup
|
||||
|
||||
Recommendation: use an explicitly owned temporary subtree with per-invocation
|
||||
ownership markers and a conservative age threshold. Normal cleanup removes the
|
||||
current invocation synchronously; opportunistic cleanup removes only marked,
|
||||
inactive directories old enough that they cannot reasonably belong to a live
|
||||
invocation.
|
||||
|
||||
Alternative: perform only synchronous cleanup and document manual removal of
|
||||
directories left by process termination. This minimizes destructive code and
|
||||
concurrency risk, but crashed processes can still accumulate unbounded files.
|
||||
|
||||
### Legacy workspace cleanup
|
||||
|
||||
Recommendation: ignore legacy run-addressed trees and document a precise,
|
||||
manual one-time cleanup procedure. Do not automatically delete them during
|
||||
startup or upgrade.
|
||||
|
||||
Alternative: add an explicit cleanup command that previews and then removes
|
||||
recognized legacy artifacts. This is more convenient for large installations
|
||||
but introduces a destructive command and a legacy-format classifier that must
|
||||
be maintained and tested.
|
||||
stateless lifecycle.
|
||||
|
||||
Reference in New Issue
Block a user