Files
weatherreporter/docs/policy/development.md

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: report-specific briefing package builders.
  • 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:

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.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.