7.5 KiB
Development Policy
This document is the contributor workflow policy for weatherreporter.
Developers and LLM coding agents should use it with
docs/policy/architecture.md and docs/policy/documentation.md.
Repository Layout
cmd/weatherreporter: binary entry point.internal/app: orchestration for generation, batches, fetch helpers, and inspection.internal/cli: command parsing, flag handling, help text, and JSON output.internal/config: configuration structs, defaults, loading, overrides, and validation.internal/fileutil: shared atomic filesystem write and copy helpers.internal/adapters/distributor: Distributor upload adapter.internal/adapters/weatherapi: Weather API HTTP adapter.internal/adapters/scriptorium: Scriptorium subprocess adapter.internal/weatherdata: normalized weather source facts, source metadata, and source warnings.internal/forecast: deterministic forecast derivation.internal/facts: collected and derived report fact contracts.internal/module: module IDs, config items, output envelopes, and snapshots.internal/report: report definitions, valid periods, batches, output names, and comparison declarations.internal/briefing: prompt-facing module value builders and module registry.internal/changes: structured Recent Changes comparison.internal/promptinput: Scriptoriumdata_packageconstruction and validation.internal/state: filesystem paths, atomic JSON writes, metadata, lookup, and inspection support.internal/timeutil: clock, date, timezone, and period helpers.docs: user, operator, developer, integration, internal, policy, and roadmap documentation.examples: maintained copyable examples.
Local Validation
Use focused checks while editing and broader checks before committing:
go test ./...
go run ./cmd/weatherreporter --help
git diff --check
Useful focused checks:
go test ./internal/cli ./internal/config
go test ./internal/app ./internal/state
go test ./internal/adapters/distributor ./internal/adapters/weatherapi ./internal/adapters/scriptorium
go test ./internal/forecast ./internal/report ./internal/briefing ./internal/changes ./internal/promptinput
Run gofmt -w on changed Go files before committing.
Coding Conventions
- Keep domain logic out of
cmd,internal/cli, and adapter packages. - Prefer small explicit structs and functions over broad framework-style abstractions.
- Keep package APIs narrow and named around implemented behavior.
- Return errors with operation, path, endpoint, report, or RunID context.
- Do not log or expose secrets.
- Use
context.Contextfor external calls, subprocesses, and orchestrated workflows that may be canceled. - Use atomic writes for durable JSON artifacts where practical.
- Keep report selection and prompt IDs centralized in
internal/report. - Keep Scriptorium argv construction inside
internal/adapters/scriptorium. - Keep distributor package types and upload-client construction inside
internal/adapters/distributor. - Keep Weather API transport and envelope handling inside
internal/adapters/weatherapi.
Dependency Policy
Prefer the Go standard library. Add dependencies only when they materially improve correctness, interoperability, security, or maintainability.
Current external dependencies:
gitea.maximumdirect.net/eric/distributorfor distributor source bundle construction and HTTP upload client behavior.gopkg.in/yaml.v3for YAML configuration parsing.
When adding a dependency:
- explain why the standard library is not enough;
- keep dependency types from leaking across unrelated package boundaries;
- add tests for the behavior the dependency supports;
- update this policy if the dependency becomes part of contributor workflow.
Configuration Changes
Configuration is owned by internal/config.
When adding or changing a field:
- update
Configand the nested config struct inconfig.go; - add or adjust defaults in
defaults.gowhen the field has a safe default; - update loading or CLI override behavior in
load.goonly when needed; - validate required values and accepted ranges in
validate.go; - add or update config tests;
- update
docs/config.mdand maintained examples when the field is user visible; - keep secrets out of example config files.
Configuration precedence is:
- CLI overrides supported by
config.LoadOptions; - configuration file values;
- built-in defaults.
The default config path is /usr/local/etc/weatherreporter/config.yml.
CLI Changes
The CLI is owned by internal/cli.
When adding or changing a command or flag:
- update help text and parser behavior together;
- convert parsed values into app-layer request structs;
- keep domain decisions in
internal/appor domain packages; - add parser or command tests in
internal/cli; - update
docs/cli.md; - update
docs/operations.mdordocs/troubleshooting.mdwhen behavior affects operators.
CLI commands should return concise actionable errors and avoid printing partial JSON when command construction fails.
Components And Adapters
Use existing package boundaries before adding a package.
Add a new internal component only when it owns a distinct implemented contract.
Define its inputs, outputs, state behavior, failure behavior, tests, and
invariants in docs/internal/.
Adapters should stay thin:
- HTTP adapters own transport, request construction, envelope handling, and decode boundaries.
- subprocess adapters own argv construction, timeout handling, stdout/stderr capture, and exit-code interpretation.
- adapter packages should not own report selection, forecast summarization, Recent Changes, or prompt input schema decisions.
When an external contract changes, update the matching file under
docs/integrations/.
Tests
Core tests must not require live Weather API, Scriptorium, or distributor services.
Preferred test patterns:
- fake command runners for subprocess behavior;
httptest.Serverfor Weather API behavior;- fake distributor upload clients for notification behavior;
- filesystem temp directories for state behavior;
- deterministic clocks for report periods and RunIDs;
- table tests for config validation, CLI parsing, period resolution, and threshold behavior.
Add focused tests near the package that owns the behavior. Use app-level tests for workflow ordering, persistence, and cross-package contracts.
Examples
Examples under examples/ must be real, maintained, and free of secrets.
When updating examples:
- use implemented config fields only;
- avoid private endpoints and credentials;
- keep comments short and operationally useful;
- add or update validation coverage when a new example file is introduced;
- link maintained examples from
docs/config.md.
Do not add generated report examples unless they can be kept current without live external services.
Documentation Checklist
Documentation updates are part of behavior changes.
Update:
README.mdfor project orientation or quickstart changes;docs/cli.mdfor command and flag changes;docs/config.mdfor config fields, defaults, and precedence changes;docs/operations.mdfor state, artifact, batch, inspection, and recovery behavior;docs/troubleshooting.mdfor recurring operator-facing failure modes;docs/internal/for component contracts and invariants;docs/integrations/for external Weather API, Scriptorium, or distributor contract changes;docs/roadmap/only for unimplemented or deferred work.
Non-roadmap docs must describe implemented behavior only.