Document Promptkit report generation
This commit is contained in:
@@ -1,112 +1,44 @@
|
||||
# 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).
|
||||
`internal/state` owns safe workspace paths, atomic artifact writes, metadata,
|
||||
prior-snapshot lookup, and read-only inspection. Operators should use the
|
||||
[operations guide](../operations.md) for lifecycle and retention.
|
||||
|
||||
## Store construction and artifact paths
|
||||
## 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.
|
||||
For each run, paths are grouped by artifact group and valid start date:
|
||||
|
||||
| Artifact | Derived location |
|
||||
| Artifact | Location |
|
||||
| --- | --- |
|
||||
| Module snapshot | `snapshots/<group>/<date>/modules.<run-id>.json` |
|
||||
| Metadata | `snapshots/<group>/<date>/metadata.<run-id>.json` |
|
||||
| Data package | `data-packages/<group>/<date>/data_package.<run-id>.yaml` |
|
||||
| Prompt preparation | `preflight/<group>/<date>/prompt_preparation.<run-id>.json` |
|
||||
| Prompt execution | `snapshots/<group>/<date>/prompt_execution.<run-id>.json` |
|
||||
| Render preflight | `preflight/<group>/<date>/render.<run-id>.json` |
|
||||
| Notification record | `notifications/<group>/<date>/distributor.<run-id>.json` |
|
||||
| Raw generated text | `snapshots/<group>/<date>/generated_text_raw.<run-id>.json` |
|
||||
| Validated generated text | `snapshots/<group>/<date>/generated_text.<run-id>.json` |
|
||||
| Render context | `snapshots/<group>/<date>/render_context.<run-id>.json` |
|
||||
| Managed report | `reports/<group>/<date>/report.<run-id>.md` |
|
||||
| Generated text | `snapshots/<group>/<date>/generated_text.<run-id>.json` |
|
||||
| Generated-text source and result | `snapshots/<group>/<date>/generated_text_raw.<run-id>.json` and `generated_text_result.<run-id>.json` |
|
||||
| Generated-text render context | `snapshots/<group>/<date>/render_context.<run-id>.json` |
|
||||
| Notification | `notifications/<group>/<date>/distributor.<run-id>.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 notification records are `notifications/batches/<batch>/<local-date>/distributor.<batch-run-id>.json`.
|
||||
|
||||
Batch Distributor notifications are derived separately as
|
||||
`notifications/batches/<batch>/<local-date>/distributor.<batch-run-id>.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 Debug Storage
|
||||
|
||||
## Metadata and durable writes
|
||||
New metadata is `weatherreporter.metadata.v2` and gains preparation and
|
||||
execution paths only after those artifacts are saved. Legacy V1 records remain
|
||||
readable; their historic preflight and generated-text-result fields are mapped
|
||||
to the corresponding preparation and execution views during inspection. New
|
||||
runs never write V1 records.
|
||||
|
||||
`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, prompt preparation,
|
||||
prompt execution, report, generated-artifact, and notification locations when
|
||||
present. New prompt records use `weatherreporter.metadata.v2`; historic
|
||||
`weatherreporter.metadata.v1` records remain readable and retain their legacy
|
||||
JSON field names when inspected.
|
||||
`PromptDebugWriter` is separate from workspace state. An empty root disables
|
||||
it. An enabled absolute root is checked for safe directories and symlinks, then
|
||||
stores `preparation.json` and `execution.json` beneath
|
||||
`<root>/<report-id>/<valid-date>/<run-id>/`. Directories are `0700`; files are
|
||||
atomic `0600`. Normal state discovery does not read this root.
|
||||
|
||||
`BuildMetadataFromBriefingMetadata` establishes legacy common fields, while
|
||||
`BuildPromptMetadataFromBriefingMetadata` establishes the V2 record. The
|
||||
application adds locations only after the corresponding artifacts are
|
||||
produced. `SaveMetadata` requires the run ID, module snapshot, data package,
|
||||
metadata path, and the matching preparation reference for its schema. The
|
||||
package also saves module snapshots, data packages, prompt preparation and
|
||||
execution records, legacy preflight records, generated-text artifacts, render
|
||||
contexts, and notifications. JSON writes use atomic replacement, so readers do
|
||||
not observe a partially written state file.
|
||||
|
||||
## Explicit prompt debug storage
|
||||
|
||||
`PromptDebugWriter` is a separate, opt-in boundary for content-rich prompt
|
||||
diagnostics. It is constructed with an explicit absolute operator root, rather
|
||||
than a workspace-derived path. A blank root produces a disabled writer that
|
||||
does not access the filesystem.
|
||||
|
||||
Enabled debug captures are grouped as
|
||||
`<root>/<report-id>/<valid-date>/<run-id>/` and contain `preparation.json` and
|
||||
`execution.json`. The writer rejects symlinks, unsafe path segments, path
|
||||
escape, and non-directory roots; it creates its directories with `0700` and
|
||||
writes files atomically with `0600`. Normal state discovery and inspection do
|
||||
not read this root. Its wire records map only approved project-owned fields;
|
||||
credentials and dependency objects are not persisted.
|
||||
|
||||
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:
|
||||
Focused checks:
|
||||
|
||||
```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.
|
||||
|
||||
Reference in New Issue
Block a user