Expand description
The machine-config settings screen: which agent each role resolves to, and a safe way to change those assignments.
Reading goes through Config::load_layers like every other consumer, so
the screen shows what a run started now would see. Writing touches one
file, the machine layer, whose path is resolved here from
Config::machine_layer (or injected by a test) and never taken from the
client - a repository’s magi.toml cannot become a write target.
toml_edit is not a dependency, so the write is a line-level patch of the
[roles] table: every byte outside the keys being changed (comments,
[vars], Tera expressions, other tables) is carried over untouched. The
patch is only a proposal. It is written to a temporary file beside the
original, the layered config is re-loaded with that file standing in for
the machine layer, and the result must say exactly what was asked for
before the original is replaced by a rename. Anything the line patcher
cannot place (an inline roles = { .. }, say) fails that check and is
refused with a readable message instead of being guessed at.
The machine file applies to every repository, so two more rules hold. The
detected roster is never written down (Config::load_layers fills agents
from PATH whenever no layer declares the key), so a role save adds no
second [[agents]] declaration and CLIs installed later are still found.
And a save is also loaded against every other checkout found under
[repos] roots and the Settings selector: one that loaded before and would
not now (it declares the same roles.* key) refuses the save in words.
Limits: checkouts outside both lists are not checked, a checkout already
broken is ignored, and another process editing a repo config between the
check and the rename is not prevented. The view shows the same lock up front.