brew: escalate writes to the prefix owner so the agent converges deps itself - #171
Merged
Merged
Conversation
… itself Homebrew assumes exactly one non-root owner of exactly one prefix, so on cooperative shared machines (plans#26) the sandboxed agent user cannot install formulae — the machine-level root cause of the plans#36 leg-2 googletest incident (brew wwise-cli EPERM). Rejected alternatives: per-user prefix (no bottles off the default prefix on Apple Silicon → source builds), host-level provisioning (a human in the loop for every new formula), group-writable prefix (fragments brew's single-owner ownership metadata). Precedent: snappy's build image already routes brew through a dedicated linuxbrew user — same pattern, designated owner. - BrewIntegration prepends sudo -n -u <prefix-owner> to brew writes (tap, install) when the prefix is not writable by the current user. The owner is stat'd at runtime — never hardcoded — and a writable prefix short-circuits to plain brew: single-user machines unchanged. A sudo -n refusal names the missing edge and its remediation. - AgentBootstrap's sudoers drop-in gains the brew edge: the agent may run exactly brew as the prefix owner, NOPASSWD. Stat'd at bootstrap, re-converged by re-running register, omitted when the host has no brew or the agent owns the prefix itself. Co-authored-by: Cursor <cursoragent@cursor.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
srb tc rejects splatting a dynamically-sized array into system() (error 7019); route the escalation argv through T.unsafe like run_brew_install already does. Cover the changed lines codecov flagged: URL-less tap registration (with and without escalation, asserting the remediation hint only appears when escalated) and brew --prefix discovery (memoized success and ENOENT-absent brew). Co-authored-by: Cursor <cursoragent@cursor.com>
JPDuchesne
added a commit
that referenced
this pull request
Sep 16, 2026
Agent-isolation and emulated-Mac fixes: install-deps failure isolation with typed errors (#170), brew escalation to the prefix owner + AgentBootstrap sudoers edge (#171), BuildKit secret files in a verified per-uid dir under the data root — colima-visible and substitution-proof (#173), build-watcher guest-load liveness signal + 15m stall window (#174), sigpending ulimit for Rosetta signal-queue aborts (#175), and brew trust before tap in docker-install-build-deps (tap-rot fix).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #170.
Homebrew assumes exactly one non-root owner of exactly one prefix, so on cooperative shared machines (d3mlabs/plans#26) the sandboxed agent user cannot install formulae — the machine-level root cause of the plans#36 leg-2 googletest incident (
brew wwise-cliEPERM abortinginstall-deps).Rejected alternatives: per-user prefix (no bottles off the default prefix on Apple Silicon → source builds), host-level provisioning (human in the loop for every new formula), group-writable prefix (fragments brew's single-owner ownership metadata; unsupported by brew). Precedent: snappy's build image already routes brew through a dedicated
linuxbrewuser because brew refuses root — same pattern, designated owner.BrewIntegrationprependssudo -n -u <prefix-owner>to brew writes (tap,install) when the prefix is not writable by the current user. Owner stat'd at runtime, never hardcoded; a writable prefix short-circuits to plainbrew(single-user machines unchanged).sudo -nrefusal surfaces "rundev runner registerto re-converge" instead of a cryptic brew failure; escalated tap failures hint at local-tap path readability.AgentBootstrap#sudoers_contentgains the brew edge: agent may run exactly the brew binary as the prefix owner, NOPASSWD. Prefix/owner stat'd at bootstrap time; re-running register re-converges; omitted when the host has no brew or the agent already owns the prefix.Test-first: all 7 new tests written and confirmed failing before the implementation. Full suite green except the 4 pre-existing
BuildContainerTestfailures (also fail on cleanmainon this machine).End-to-end verification on this machine (after merge): re-run
dev runner register, thendev install-depsasai-agentin the snappy workspace — the previously failingwwise-cliinstall should succeed unattended.Made with Cursor