215 lines
9.4 KiB
Markdown
215 lines
9.4 KiB
Markdown
# Architecture Policy
|
|
|
|
## 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.
|
|
|
|
## 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.
|
|
|
|
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 primary flow is:
|
|
|
|
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.
|
|
|
|
Inspection is a separate read-only flow over persisted state. It must not
|
|
collect weather data, invoke Scriptorium, or upload reports.
|
|
|
|
## Ownership And Dependency Direction
|
|
|
|
### Entry Point And CLI
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
## 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.
|