diff --git a/nix/agent-modules/user.nix b/nix/agent-modules/user.nix index f521301f..a044ddd6 100644 --- a/nix/agent-modules/user.nix +++ b/nix/agent-modules/user.nix @@ -209,8 +209,12 @@ in if [ -d "/agents/$userName/harness" ]; then chown -hR "$userName:$userName" "/agents/$userName/harness" 2>/dev/null || true fi + # work/ holds large build trees and the agent creates everything in + # it, so only an ownership mismatch on the top dir needs a full walk. if [ -d "/agents/$userName/work" ]; then - chown -hR "$userName:$userName" "/agents/$userName/work" 2>/dev/null || true + if [ "$(stat -c %U "/agents/$userName/work")" != "$userName" ]; then + chown -hR "$userName:$userName" "/agents/$userName/work" 2>/dev/null || true + fi fi # The socket dir is bind-mounted from the host, where hive-priv creates # it `0751 root`. The harness binds its sockets here as this user; the diff --git a/nix/module-eval/agent-user.nix b/nix/module-eval/agent-user.nix index 2be03f84..7a076a3d 100644 --- a/nix/module-eval/agent-user.nix +++ b/nix/module-eval/agent-user.nix @@ -30,7 +30,9 @@ let # hive-c0re creates the host work dir as hive-core; this activation is # the only thing that lets the agent write to it. name = "the agent's activation hands its own work dir to the agent user"; - ok = lib.hasInfix ''chown -hR "$userName:$userName" "/agents/$userName/work"'' migrate; + ok = + lib.hasInfix ''if [ "$(stat -c %U "/agents/$userName/work")" != "$userName" ]; then'' migrate + && lib.hasInfix ''chown -hR "$userName:$userName" "/agents/$userName/work"'' migrate; } { # hive-priv creates the host socket dir `0751 root` and never chowns it,