Document Promptkit report generation
This commit is contained in:
@@ -2,213 +2,72 @@
|
||||
|
||||
## Purpose
|
||||
|
||||
This policy defines Weatherreporter's system shape, normative ownership,
|
||||
dependency direction, architectural invariants, safety properties, and
|
||||
non-goals. Developers and coding agents should use it to preserve the
|
||||
application's boundaries as the implementation evolves.
|
||||
|
||||
The [development guide](../development.md) owns the current package inventory
|
||||
and contributor workflow. Focused documents under `docs/internal/` own
|
||||
implemented subsystem mechanics. This policy owns the rules those packages and
|
||||
mechanics must preserve.
|
||||
This policy defines Weatherreporter's system shape, ownership, dependency direction,
|
||||
and safety invariants. The [development guide](../development.md) owns the
|
||||
package inventory; focused documents in `docs/internal/` own implementation detail.
|
||||
|
||||
## System Shape
|
||||
|
||||
Weatherreporter is a deterministic weather briefing and report-preparation CLI.
|
||||
It consumes normalized weather data, derives report facts and module snapshots,
|
||||
builds curated prompt packages, compares structured snapshots with prior runs,
|
||||
and invokes Scriptorium either to produce managed Markdown directly or to
|
||||
produce bounded generated-text prose for repository-owned templates. It
|
||||
persists inspectable artifacts and can upload completed reports through
|
||||
Distributor.
|
||||
Weatherreporter is a deterministic weather-report CLI. It collects normalized
|
||||
weather data, derives facts and modules, builds a curated YAML data package,
|
||||
compares prior snapshots, executes exact-version Promptkit prompts, validates
|
||||
structured generated prose, and renders repository-owned Markdown. Completed
|
||||
managed Markdown may be uploaded through Distributor.
|
||||
|
||||
The application is intentionally a small, explicit, dependency-light Go
|
||||
program. Add abstraction only when it protects a real boundary, makes an
|
||||
important invariant testable, or supports an implemented extension point.
|
||||
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.
|
||||
|
||||
The primary flow is:
|
||||
## Ownership And Boundaries
|
||||
|
||||
1. CLI parsing and configuration resolution;
|
||||
2. report or batch resolution;
|
||||
3. normalized weather collection;
|
||||
4. deterministic fact derivation and module construction;
|
||||
5. structured prior-snapshot comparison;
|
||||
6. curated prompt input and report-mode-specific Scriptorium processing;
|
||||
7. generated-text validation when applicable, managed Markdown production,
|
||||
and metadata persistence; and
|
||||
8. optional notification using managed report artifacts.
|
||||
- `internal/cli` owns command parsing, help, summaries, and one executor
|
||||
construction per action.
|
||||
- `internal/config` owns defaults, loading, validation, and secret loading.
|
||||
- `internal/app` owns workflow order, partial results, and notification
|
||||
coordination through project-owned contracts.
|
||||
- Deterministic domain packages own weather derivation, report periods, modules,
|
||||
generated-text validation, and template contexts.
|
||||
- `internal/adapters/weatherapi`, `internal/adapters/promptkit`, and
|
||||
`internal/adapters/distributor` own their external dependency mechanics.
|
||||
- `internal/state` owns workspace paths, V2 metadata, atomic persistence, and
|
||||
read-only inspection.
|
||||
|
||||
Inspection is a separate read-only flow over persisted state. It must not
|
||||
collect weather data, invoke Scriptorium, or upload reports.
|
||||
Dependency-specific Promptkit types remain inside its adapter. The application
|
||||
does not parse flags, construct provider clients, or render provider output
|
||||
directly.
|
||||
|
||||
## Ownership And Dependency Direction
|
||||
## Prompt Execution Invariants
|
||||
|
||||
### Entry Point And CLI
|
||||
- Prompts receive curated module packages, never unbounded raw weather payloads.
|
||||
- Every execution inspects the exact prompt version and output contract before
|
||||
collection. The selected profile is configured explicitly or declared by the
|
||||
prompt; unsupported direct-key profiles and missing reported credentials fail
|
||||
before collection.
|
||||
- Prepared execution persists safe preparation provenance before provider work.
|
||||
Completed execution persists safe execution provenance; raw output is
|
||||
validated before template rendering.
|
||||
- Generated text fills defined prose slots only. Deterministic facts remain
|
||||
authoritative and repository-owned templates produce all managed Markdown.
|
||||
- Sensitive rendered prompts, schemas, input bodies, provider endpoints, and
|
||||
credentials never enter normal metadata, summaries, logs, or workspace
|
||||
artifacts. They are written only to an explicit secure debug root when
|
||||
requested.
|
||||
|
||||
The binary entry point should do no business work beyond constructing and
|
||||
running the CLI. CLI code owns commands, arguments, flags, help, output
|
||||
formatting, and conversion into application requests.
|
||||
## State, Notification, And Testing Invariants
|
||||
|
||||
CLI packages must not own meteorological decisions, report composition,
|
||||
artifact layout, Recent Changes comparison, external transport, or subprocess
|
||||
construction.
|
||||
|
||||
### Configuration
|
||||
|
||||
Configuration loading, built-in defaults, overrides, secret loading, and
|
||||
validation belong to `internal/config`. Operational values shared across
|
||||
packages must be explicit configuration or constants owned by the responsible
|
||||
package, not hidden in CLI or adapter code.
|
||||
|
||||
The exact configuration contract belongs in the
|
||||
[configuration reference](../config.md). Other architecture documents should
|
||||
state ownership and safety rules rather than repeat fields, defaults, or
|
||||
precedence.
|
||||
|
||||
### Application Orchestration
|
||||
|
||||
`internal/app` owns top-level use cases and workflow order. It composes report
|
||||
resolution, collection, domain transformations, state, rendering, and optional
|
||||
notification through narrow project-owned contracts.
|
||||
|
||||
The application layer may coordinate components and convert between their
|
||||
contracts. It must not absorb CLI parsing, HTTP transport, subprocess argument
|
||||
construction, filesystem layout, weather derivation algorithms, template
|
||||
execution, or adapter-specific dependency types.
|
||||
|
||||
### Domain And Report Logic
|
||||
|
||||
Meteorological selection, forecast-period resolution, daypart grouping,
|
||||
threshold detection, fact derivation, report composition, module construction,
|
||||
generated-text validation, and Recent Changes comparison belong in deterministic
|
||||
Go domain packages.
|
||||
|
||||
Domain packages must not depend on CLI parsing, process execution, remote
|
||||
transport, or concrete external-library types. Given the same normalized
|
||||
inputs, configuration, valid period, prior snapshot, and clock, domain behavior
|
||||
should be reproducible.
|
||||
|
||||
Report selection must go through the report registry or an equivalent
|
||||
centralized mechanism. A report definition owns its identity, prompt and
|
||||
rendering mode, valid-period resolver, module composition, comparison strategy,
|
||||
artifact grouping, and output naming. Do not scatter report-ID conditionals
|
||||
through CLI, orchestration, or adapters.
|
||||
|
||||
### External Adapters
|
||||
|
||||
External integrations use adapter boundaries under `internal/adapters`.
|
||||
Adapters own transport and protocol mechanics; application and domain packages
|
||||
own decisions.
|
||||
|
||||
- The Weather API adapter owns HTTP request construction, timeouts, retries,
|
||||
response-envelope handling, decoding, and endpoint compatibility.
|
||||
- The Scriptorium adapter owns argument construction, context-aware subprocess
|
||||
execution, stdout and stderr capture, exit interpretation, and result
|
||||
decoding. It must avoid shell interpolation.
|
||||
- The Distributor adapter owns dependency-specific bundle and upload types,
|
||||
client construction, request execution, status handling, and redaction.
|
||||
|
||||
External dependency types must not leak beyond the adapter that integrates
|
||||
them. Adapters should expose narrow project-owned inputs and outputs so an
|
||||
integration can be tested or replaced without changing domain logic.
|
||||
|
||||
### State And Embedded Assets
|
||||
|
||||
`internal/state` owns managed workspace paths, durable metadata, atomic
|
||||
artifact persistence, prior lookup, and inspection reads. Other packages should
|
||||
request state operations rather than reconstruct managed paths independently.
|
||||
|
||||
Schemas, prompts, Markdown templates, and partials should live as separate
|
||||
repository assets and be embedded by the package that owns their execution or
|
||||
lookup. Keep weather derivation and path construction out of templates.
|
||||
|
||||
## Architectural Invariants
|
||||
|
||||
### Weather Truth And Generated Text
|
||||
|
||||
- Normalized source data and deterministic Go derivation are authoritative for
|
||||
weather facts.
|
||||
- LLM prompts receive curated module-based packages rather than raw,
|
||||
unbounded source payloads.
|
||||
- Generated text is limited to defined prose slots, validated before use, and
|
||||
rendered through typed or otherwise explicit contexts.
|
||||
- Repository-owned templates arrange validated prose and deterministic facts;
|
||||
they do not perform meteorological derivation.
|
||||
|
||||
### Reports And Comparison
|
||||
|
||||
- Report behavior is resolved through centralized definitions.
|
||||
- Recent Changes is computed from structured module snapshots, never by
|
||||
comparing rendered Markdown.
|
||||
- Batch workflows collect normalized weather data once and reuse that
|
||||
collection for planning and report generation.
|
||||
- Report metadata links identity, generation time, valid period, source
|
||||
provenance, and the managed artifacts produced for the run.
|
||||
|
||||
### Managed State And Notification
|
||||
|
||||
- Durable structured writes are atomic where practical.
|
||||
- Managed paths remain beneath the configured workspace root.
|
||||
- Operations that delete, move, overwrite, or copy files use narrow, explicit
|
||||
paths; destructive cleanup is opt-in.
|
||||
- Intermediate artifacts reached before a later failure remain inspectable
|
||||
where practical.
|
||||
- Distributor uploads use managed Markdown reports, never optional output
|
||||
copies or broad workspace scans.
|
||||
- Notification occurs only after the managed report and required metadata have
|
||||
been successfully produced.
|
||||
|
||||
### Security, Errors, And Cancellation
|
||||
|
||||
- Secrets must not appear in logs, errors, persisted artifacts, examples, or
|
||||
user-facing output.
|
||||
- Errors preserve actionable operation, report, RunID, path, endpoint, or
|
||||
subprocess context without exposing secrets or unnecessarily large payloads.
|
||||
- External calls, subprocesses, storage operations, and multi-step workflows
|
||||
accept or propagate `context.Context` where cancellation or timeout is
|
||||
meaningful.
|
||||
- Adapter failures preserve useful status, stderr, or response context at the
|
||||
boundary and are translated into project-owned errors before crossing into
|
||||
unrelated packages.
|
||||
|
||||
## Dependency Policy
|
||||
|
||||
Prefer the Go standard library. Add an external dependency only when it
|
||||
materially improves correctness, security, interoperability, or
|
||||
maintainability. A dependency used for a small convenience does not justify its
|
||||
lifetime upgrade and compatibility cost.
|
||||
|
||||
Keep dependency-specific types inside the package that intentionally adopts
|
||||
the dependency. The application should remain understandable and testable
|
||||
without requiring framework-wide abstractions or live external services.
|
||||
|
||||
## Verification And Documentation
|
||||
|
||||
Core behavior must be testable without live Weather API, Scriptorium, or
|
||||
Distributor services. The [testing policy](testing.md) owns test philosophy,
|
||||
sufficiency, boundaries, and test-double guidance.
|
||||
|
||||
Documentation must follow the
|
||||
[documentation policy](documentation.md). Update the canonical user,
|
||||
operator, integration, internal, and example documentation in the same change
|
||||
as the behavior it describes. Future or proposed behavior belongs under
|
||||
`docs/roadmap/`; significant durable decisions may be recorded as ADRs.
|
||||
- Managed writes are atomic where practical and stay beneath the configured
|
||||
workspace root. Reached artifacts remain inspectable after later failures.
|
||||
- New records use `weatherreporter.metadata.v2`; V1 records remain readable for
|
||||
inspection compatibility.
|
||||
- Distributor uploads use only the managed Markdown report, never output copies
|
||||
or workspace scans. Notification follows report and final metadata success.
|
||||
- Default tests are deterministic, offline, and use Promptkit/provider fakes
|
||||
rather than live provider calls. See the [testing policy](testing.md).
|
||||
|
||||
## Non-Goals
|
||||
|
||||
Weatherreporter is not:
|
||||
|
||||
- a source weather-data ingestion or normalization service;
|
||||
- a general-purpose LLM orchestration framework;
|
||||
- an application in which an LLM selects authoritative weather facts or report
|
||||
policy;
|
||||
- a plugin framework with dynamically discovered report or module behavior;
|
||||
- an HTTP service or multi-user distributed job system;
|
||||
- a replacement for Scriptorium or Distributor protocol ownership; or
|
||||
- a system that hides operational state exclusively inside opaque logs or
|
||||
remote services.
|
||||
|
||||
New requirements may justify revisiting a non-goal. A change that alters system
|
||||
shape, dependency direction, a safety property, or another architectural
|
||||
invariant should be recorded deliberately in this policy or an ADR rather than
|
||||
introduced implicitly.
|
||||
Weatherreporter is not a weather-data ingestion service, general LLM
|
||||
orchestration framework, plugin platform, HTTP service, multi-user job system,
|
||||
or a replacement for Promptkit or Distributor.
|
||||
|
||||
@@ -87,7 +87,7 @@ mechanisms, not secret values.
|
||||
| Operations | `docs/operations.md` | Normal workflows, physical workspace layout, artifacts and metadata, inspection, notification behavior, recovery, cleanup, permissions, and operational caveats. | Complete CLI syntax, configuration field definitions, logical external contracts, and implementation mechanics. |
|
||||
| Troubleshooting | `docs/troubleshooting.md` | Recurring symptoms, likely causes, diagnostic steps, safe fixes, and links to normal-operation references. | Complete command and configuration references, routine operating procedures, and implementation detail. |
|
||||
| Report template surface | `docs/templates.md` | Implemented template files and partials, render-context fields, editing rules, and maintainer-facing template examples. | Weather derivation, module implementation, generated-text validation internals, and operator procedures. |
|
||||
| External and durable integration contracts | `docs/integrations/` | Weather API, Scriptorium, Distributor, external formats and protocols, durable logical paths and schemas, compatibility behavior, and upstream or downstream responsibilities. | Physical runtime placement and lifecycle, internal transformations, CLI syntax, and configuration defaults. |
|
||||
| External and durable integration contracts | `docs/integrations/` | Weather API, Promptkit, Distributor, external formats and protocols, durable logical paths and schemas, compatibility behavior, and upstream or downstream responsibilities. | Physical runtime placement and lifecycle, internal transformations, CLI syntax, and configuration defaults. |
|
||||
| Internal subsystem behavior | `docs/internal/` | Implementation flow, internal collaborators and state transitions, package-local guarantees and failures, and relevant tests. | Global architecture invariants, user-facing contracts, external schemas, operator procedures, and future package plans. |
|
||||
| Architectural decision history | `docs/adr/`, when repository-local decisions require records | Significant decisions, context, alternatives, rationale, consequences, and supersession history. | Current behavior reference, implementation status, and task sequencing. |
|
||||
| Temporary feature roadmaps | `docs/roadmap/`, while planned work needs coordination | Proposed, accepted, deferred, or rejected work; sequencing; gates; implementation status; and task breakdowns. | Implemented behavior reference and durable decision rationale. |
|
||||
|
||||
@@ -54,8 +54,8 @@ Use a classical or Detroit-style approach:
|
||||
- Test exact collaborator interactions only when the interaction itself is a
|
||||
requirement.
|
||||
|
||||
Weatherreporter's important seams include clocks, subprocesses, HTTP services,
|
||||
Distributor uploads, filesystem roots, environment-backed secrets, and any
|
||||
Weatherreporter's important seams include clocks, Promptkit executors, HTTP
|
||||
services, Distributor uploads, filesystem roots, environment-backed secrets, and any
|
||||
future source of randomness or nondeterminism.
|
||||
|
||||
## Execution Requirements
|
||||
@@ -73,7 +73,7 @@ package command while iterating and `go test -race ./...` when the risk crosses
|
||||
package boundaries.
|
||||
|
||||
Tests in the default suite must be deterministic, offline, and independent of
|
||||
real credentials. They must not invoke live Weather API, Scriptorium, or
|
||||
real credentials. They must not invoke live Weather API, Promptkit providers, or
|
||||
Distributor services or depend on other mutable external infrastructure.
|
||||
Tests that require live infrastructure must be explicitly opt-in and clearly
|
||||
separated from the default suite.
|
||||
@@ -198,7 +198,7 @@ Each behavior should have a clear test owner:
|
||||
- CLI parser tests own arguments, flags, and command construction.
|
||||
- Config tests own loading, precedence, defaults, secrets, and validation.
|
||||
- Domain tests own weather transformations and invariants.
|
||||
- Adapter tests own HTTP, subprocess, and upload boundaries.
|
||||
- Adapter tests own HTTP, Promptkit/provider, and upload boundaries.
|
||||
- Orchestrator tests own workflow ordering, persistence, partial success, and
|
||||
failure propagation.
|
||||
- State tests own path derivation, atomic artifacts, lookup, and round trips.
|
||||
@@ -220,7 +220,7 @@ observation:
|
||||
4. Use mocks when the interaction itself is contractual.
|
||||
|
||||
Mocks are appropriate for requirements such as uploading exactly once, saving
|
||||
metadata before notification, propagating cancellation to Scriptorium, or
|
||||
metadata before notification, propagating cancellation to Promptkit, or
|
||||
avoiding an external call after an earlier workflow failure. Do not use mocks
|
||||
merely to isolate every object or reproduce the implementation's call graph.
|
||||
|
||||
@@ -232,7 +232,7 @@ Use:
|
||||
- `t.TempDir()` for real filesystem behavior;
|
||||
- `httptest.Server` for realistic Weather API interactions;
|
||||
- test-controlled clocks for periods and RunIDs;
|
||||
- fake command runners for Scriptorium behavior;
|
||||
- fake Promptkit executors or provider clients for Promptkit behavior;
|
||||
- fake upload clients for Distributor behavior;
|
||||
- fuzz tests when parsers, normalization, or path handling have a broad and
|
||||
consequential input space;
|
||||
|
||||
Reference in New Issue
Block a user