# State Internals The `internal/state` package owns filesystem-backed run state: safe path derivation, metadata persistence, prior-report lookup, and read-only report inspection. It does not decide which reports to generate or deliver. For the operator-facing layout and retention procedures, see the [operations guide](../operations.md). ## Store construction and artifact paths `NewFilesystemStore` requires a workspace root and rejects absolute or escaping values for every configured state directory. `Paths` then validates a run ID and artifact group before deriving all paths from the report's valid start date (`YYYY-MM-DD`). This keeps a run's artifacts together while making the paths safe to use below the configured workspace. | Artifact | Derived location | | --- | --- | | Module snapshot | `snapshots///modules..json` | | Metadata | `snapshots///metadata..json` | | Data package | `data-packages///data_package..yaml` | | Render preflight | `preflight///render..json` | | Notification record | `notifications///distributor..json` | | Managed report | `reports///report..md` | | Generated text | `snapshots///generated_text..json` | | Generated-text source and result | `snapshots///generated_text_raw..json` and `generated_text_result..json` | | Generated-text render context | `snapshots///render_context..json` | The configured notification root separates notification artifacts from report artifacts; single-report notification paths use the report's valid date. Report producers create parent directories as needed and write the report body; state is responsible for the surrounding paths and saved run artifacts. Batch Distributor notifications are derived separately as `notifications/batches///distributor..json`. Their date is calculated from the batch start in its configured location, and the batch identity and run ID receive the same path-segment validation as single-report artifact identifiers. ## Metadata and durable writes `Metadata` is the durable inventory for a run. It records its schema version, run identity, generated and valid timestamps, artifact group, source content and provenance, and the module snapshot, data-package, preflight, report, generated-artifact, and notification locations when present. `BuildMetadataFromBriefingMetadata` establishes the common fields; the application adds locations as artifacts are produced. `SaveMetadata` requires the run ID and the module snapshot, data-package, preflight, and metadata paths. The package also saves module snapshots, data packages, preflight records, generated-text artifacts, render contexts, and notifications. JSON writes use `fileutil.WriteJSONAtomic`, so readers do not observe a partially written state file. The data package itself follows the shared [prompt-input contract](prompt-input.md). Report text, templates, and external delivery payloads remain owned by their respective packages and integration references. ## Prior reports and inspection `FindPriorSnapshot` searches metadata rather than guessing from filenames. It only considers an earlier compatible report in the same artifact group and supports the comparison strategies defined by the report request: - `same_valid_date` finds an earlier generated report for the same valid day. The newest eligible metadata record wins; the current run is excluded. Unreadable or malformed candidate metadata is ignored so a damaged historical record does not block a new run. `ListReports` walks saved metadata, returns results ordered newest-first by generation time, and treats a missing snapshots directory as an empty history. `LoadMetadataByRunID` builds on that inspection path. These APIs are read-only; repairing or pruning stored state is an operational concern. ## Boundaries and verification The package rejects unsafe path components and incomplete metadata before writing. Callers must provide a valid report request, artifact group, and store configuration. Its focused tests cover path derivation, atomic persistence, metadata validation, comparison eligibility, and report listing: ```sh go test ./internal/state ``` See [application orchestration](app-orchestration.md) for the order in which these artifacts are created and [report templates](../templates.md) for the user-facing report contract.