--- topic: building it status: accepted date: 2026-10-02 deciders: jochen reconstructed: false extends: 02-DECISIONS/0011-managed-files-are-generated-never-edited.md --- # 174. A node varies a module through settings and kept regions, never through an edit ## Context [ADR 0011](0011-managed-files-are-generated-never-edited.md) says a managed file is derived and an edit to it is overwritten without warning. The predecessor said the same and then undid it twice: a `merge` strategy that adopted disk drift back into its database, so a local edit became the record; and a theming layer of about 90 environment variables substituted into templates at sync time, with tools to list and set them, so that *nearly every value was a variable* — a second configuration language laid over the first. The operator wants both the variation and the rule. One window-manager module with one default configuration, and each node tweaking it; and the file carrying the wanted value rather than a variable the file reads. Two mechanisms already exist for exactly this: a **setting**, declared by the module and set per mesh or per node, rendered at composition (`${setting:…}` is live in the resolver's manifest); and a **kept region**, a block in a file the mesh writes *into* where the operator's own lines survive every push ([ADR 0102](0102-the-mesh-writes-into-a-shared-file-never-over-it.md), used by the ssh-client module for the operator's own `Host` blocks). What stands in the way is [issue 168](../04-ISSUES/168-a-setting-reaches-every-file-and-contribution/00-report.md): a setting today reaches every mergeable file and every contribution of its module. Ninety theme knobs on that mechanism would reach ninety files. The record that fixes it — a setting declared with its type, meaning, default and the file it lands in — is proposed in an open change alongside the container-runtime records. ## Considered Options 1. **Carry the predecessor's merge strategy.** A local edit is adopted into the node's layer. Rejected: two writers and no arbiter, which is the option 0011 removed, and the reason a `/model` choice was silently reverted on every node for weeks before anyone found the cause. 2. **Carry the environment-variable theming.** Rejected by the operator: the value belongs in the file; a variable the file reads is a second place for the same fact. 3. **A per-node file override** — a whole file replaced for one node. Rejected: it is a flavor under another name, and a module update then misses that node entirely. 4. **Settings rendered into the file, and kept regions, and nothing else.** Chosen. ## Decision **A node varies a module in exactly two ways.** - **A setting.** Declared by the module with a default, set for the mesh or for one node, rendered into the file at composition. The value is in the file. Asked, the mesh lists every setting with its effective value and where it came from. - **A kept region.** A marked block in a file the mesh writes into, in which the operator's own lines are kept across every push and given back when the module goes (ADR 0102). **An edit outside a kept region is overwritten, as ADR 0011 says, and never adopted.** Nothing reads a managed file back into the record. **The predecessor's theme knobs become settings** of the modules whose files they render — the window manager's colours are the window manager's settings, the bar's are the bar's — each landing in the file that reads it and no other. **Issue 168 is fixed before any environment module declares a setting.** A setting must name the file it lands in; until that ships, the environment modules carry their defaults in their files and no settings. ## Consequences - No flavors, no per-node file copies, no environment layer. A module's definition is one set of files; a node's difference is data in its layer, visible by asking. - The settings record proposed alongside the container-runtime records is on the critical path of every module with a knob, and this record depends on it shipping as proposed. - A kept region is the only place a person edits a managed file, and the file says where it is. The operator's own prompt customisations, aliases and window rules live there. - What got harder: a change that is neither a setting the module declared nor the operator's own lines has no home, and is refused by the mechanism rather than silently kept. That is the point. ## How it is checked | Rule | Checked by | |---|---| | A setting reaches only the file its declaration names | the controller's settings tests, once the proposed record ships; issue 168 closes on it | | A kept region survives a push with its content and is given back on undeclare | the host's write-into tests (ADR 0102), with a region declared by an environment module | | An edit outside a region does not survive a push | the same tests, asserting the file equals the composed content outside the region | | Every effective value names its source | `mesh-controller.settings` and the module's own `show-config` tool | ## References - [Research 018](../01-RESEARCH/018-the-operators-machine-as-modules/01-the-intended-behaviour.md) §"One default, varied by settings, never by edits" - [ADR 0011](0011-managed-files-are-generated-never-edited.md), [ADR 0102](0102-the-mesh-writes-into-a-shared-file-never-over-it.md), [issue 168](../04-ISSUES/168-a-setting-reaches-every-file-and-contribution/00-report.md)