# 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`: Scriptorium `data_package` construction 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: ```bash go test ./... go run ./cmd/weatherreporter --help git diff --check ``` Useful focused checks: ```bash 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.Context` for 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/distributor` for distributor source bundle construction and HTTP upload client behavior. - `gopkg.in/yaml.v3` for 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 `Config` and the nested config struct in `config.go`; - add or adjust defaults in `defaults.go` when the field has a safe default; - update loading or CLI override behavior in `load.go` only when needed; - validate required values and accepted ranges in `validate.go`; - add or update config tests; - update `docs/config.md` and maintained examples when the field is user visible; - keep secrets out of example config files. Configuration precedence is: 1. CLI overrides supported by `config.LoadOptions`; 2. configuration file values; 3. 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/app` or domain packages; - add parser or command tests in `internal/cli`; - update `docs/cli.md`; - update `docs/operations.md` or `docs/troubleshooting.md` when 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.Server` for 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.md` for project orientation or quickstart changes; - `docs/cli.md` for command and flag changes; - `docs/config.md` for config fields, defaults, and precedence changes; - `docs/operations.md` for state, artifact, batch, inspection, and recovery behavior; - `docs/troubleshooting.md` for 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.