diff --git a/nix/agent-modules/mcp.nix b/nix/agent-modules/mcp.nix index d5e9f5a6..151bbd00 100644 --- a/nix/agent-modules/mcp.nix +++ b/nix/agent-modules/mcp.nix @@ -375,6 +375,14 @@ in # inherits the value from the daemon, so the ordering covers the # whole subtree and not just this process. OOMScoreAdjust = 500; + # systemd's default is `stop`, which tears the whole unit down as + # soon as the kernel kills *any* process in its cgroup — so one + # over-large subagent takes the daemon and every sibling session + # with it, which is the blast radius that makes an OOM here + # expensive. `continue` scopes the loss to the process the kernel + # actually chose and leaves the daemon serving, which is also what + # lets it report the kill rather than vanish and be restarted. + OOMPolicy = "continue"; User = userName; Group = userName; } diff --git a/nix/module-eval.nix b/nix/module-eval.nix index ace26482..25208745 100644 --- a/nix/module-eval.nix +++ b/nix/module-eval.nix @@ -1402,6 +1402,16 @@ let in sub > 0 && own < 0 && sub > own; } + { + # The pair the case above only makes sense with: preferring this unit + # as the victim is an improvement only if losing one subagent isn't + # losing all of them. systemd's default `stop` would take the daemon + # and every sibling session down with whichever process the kernel + # chose, which is the blast radius that made the preference a bad + # trade in the first place. + name = "one subagent losing the OOM draw does not stop the daemon"; + ok = (agentSubagentDaemon agentUncapped).serviceConfig.OOMPolicy == "continue"; + } { # The doctrine three glue files state, as a property a rewrite has to # keep: a client is defined by holding a certificate the store accepts,