WIP checkpoint committed by Claude while Atlas was still in its final verification wave. Committed early deliberately: 11 files were sitting uncommitted with two of them untracked, and untracked files in this tree have been destroyed twice today by agent git cleanup -- the user's multi-provider-support plan and a config.local.yaml holding their tariff. Protecting the work cost nothing; losing it would have cost a whole plan. Deployment-specific values previously lived as an UNCOMMITTED modification to the tracked config/config.yaml. That arrangement failed seven times in one session: three agent checkout/stash/restore calls, two `git commit -am` sweeps that each needed a history rewrite, one ordinary branch switch, and one cleanup during this very plan. Once a value is correctly absent from git, every checkout, switch, pull and rebase wipes it -- that is the intended fix behaving as designed, which is what makes the arrangement itself the bug. load_config now deep-merges an optional config/config.local.yaml over the base before validation, so every consumer inherits it (poller, feedback, eval_proficiency, seed_local_dispatch_energy, admin, dispatcher). Mappings deep-merge; lists replace wholesale; the MERGED result is validated once so extra="forbid" still catches an overlay typo. The admin portal now writes to the overlay and never to config/config.yaml. An operator changing a knob in a loopback-only portal is making a local operational decision, not a project decision -- someone changing a project default edits config.yaml and commits it through git. This also removes the shadowing trap by construction rather than guarding against it. config/config.yaml stops being dirty in normal operation, which removes the condition behind every clobbering above. NOTE: final verification wave had not reported when this was committed. The suite was green at 1155 before it started; Atlas may amend or add commits on top. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VRQXz5SYZYVWscxS1QqF6U
1.3 KiB
Local Overlay (config/config.local.yaml)
config.local.yaml is a gitignored, deep-merged overlay on top of the
tracked config/config.yaml. Anything placed in the overlay takes
precedence when load_config() merges the two files — the overlay only
needs the keys you want to change; everything else falls through to the
base.
What belongs in the overlay
Values that are specific to your machine or deployment and would turn
config/config.yaml dirty if tracked:
local_energy.enabled+local_energy.tariff_usd_per_kwh— metering per-machine, tariff often differs between sites.classifier.base_url/verification.base_url— Ollama may live on a different host or VPN address on each box.- Any tuning knob you change between machines (
num_ctxoverrides, per-host profile tweaks).
What does NOT belong here
Secrets. Secrets (NEURALWATT_API_KEY, etc.) stay in .env. The
overlay is YAML loaded as configuration, not as a credential store.
A dirty config/config.yaml is a smell
If your working copy of config/config.yaml is modified, someone edited
the shared defaults by hand. Move those edits into a new entry in
config.local.yaml — the base file should stay clean enough to commit
and share.
See config/config.local.yaml.example for concrete key examples.