Skip to content

feat: say so at init when roar shares the workload's environment - #292

Merged
christophergeyer merged 1 commit into
rc/0.4.4from
cg/warn-shared-venv-install
Aug 19, 2026
Merged

christophergeyer merged 1 commit into
rc/0.4.4from
cg/warn-shared-venv-install

Conversation

@christophergeyer

@christophergeyer christophergeyer commented Aug 19, 2026

Copy link
Copy Markdown
Member

Follow-up to #287, which was closed. That PR tried to fix one of these costs; this one recommends avoiding both.

Why a separate environment

Installing roar into the workload's own environment costs two things:

Version conflicts. Both sets of requirements have to resolve together, so roar's pins can collide with the project's.

Lineage noise. roar's dependencies are loaded into the traced process and recorded alongside the project's. Measured on an import requests workload, the freeze carries nine packages that belong to roar:

[PyYAML, annotated_types, blake3, certifi, charset-normalizer, click, cryptography,
 idna, pydantic, pydantic_core, requests, tomli, typing_extensions, typing_inspection, urllib3]

Five belong to the project.

They cannot be separated after the fact. roar's copy of a package and the workload's are the same file at the same path, so nothing — path, name, or dist metadata — can attribute them. Subtracting by name once stripped the workload's own tqdm and typing-extensions (P0-28), which is why roar_footprint_paths abstains and the freeze over-includes instead.

#287 attempted an algorithmic fix by snapshotting sys.modules at the end of bootstrap and subtracting. Measured across both layouts, with and without ROAR_WRAP, its output was byte-identical to base — roar's dependencies load lazily, after the boundary (231 modules post-boundary, including pydantic: 40, click: 12), so the snapshot held only roar's own package, already excluded twice over. It also introduced a latent false negative, so it was closed.

What this does

One hint at roar init:

hint: roar is installed in the same environment as your project. We recommend
hint: running roar from its own virtual environment: it prevents version
hint: conflicts and keeps them out of your lineage.
hint:   uv tool install roar-cli    # uv:   https://astral.sh/uv
hint:   pipx install roar-cli       # pipx: sudo apt install pipx | brew install pipx

At init, not per run. The condition is a property of how roar was installed, not of any one run, and a per-run warning is noise people learn to skip. It rides the existing hint machinery, so roar config set hints.enabled false already silences it. Both uv and pipx are offered, with install routes, since not everyone has uv.

The check compares against the WORKLOAD's interpreter, not roar's

This is the whole of it. Under uv tool or pipx, roar runs from its own venv and therefore always sits inside its own sys.prefix — so comparing roar against itself reports every correctly isolated install as shared, nagging exactly the users who took the advice. An earlier revision of this PR did precisely that.

Resolution mirrors a shell's: active virtualenv, else conda env, else the first python on PATH. Unresolvable means stay quiet.

Testing

Verified against real installers built from this branch, running the real roar shim:

layout hints printed warning
uv tool install + project venv active 23 none
uv tool install, no venv active 23 none
uv pip install into the project venv, active 23 fires
pipx install + project venv active 23 none
pipx install, no venv active 23 none

The hint count is the control: it confirms the hint machinery ran, so the zeros mean "correctly silent" rather than "output suppressed".

Seven unit tests over the same layouts (pip-into-venv, tool install with and without an active venv, system install, conda, unresolvable), each verified to fail against the naive roar-vs-its-own-prefix comparison — three of them do. Detection cannot raise; a cosmetic hint must not be able to break roar init.

Full suite: 14 failures, identical to clean rc/0.4.4 in this environment — zero new. (Local env artifacts: osmo needs network, crossenv needs specific setup; CI passes them.)

🤖 Generated with Claude Code

@christophergeyer
christophergeyer force-pushed the cg/warn-shared-venv-install branch 2 times, most recently from 93a1380 to b67d60a Compare August 19, 2026 15:30
@christophergeyer
christophergeyer force-pushed the cg/warn-shared-venv-install branch from b67d60a to 8b6c9e2 Compare August 19, 2026 15:31
Installing roar into the workload's own environment has two costs, and the
hint names both rather than dwelling on either.

Both sets of requirements must resolve together, so roar's pins can
collide with the project's. And roar's dependencies are loaded into the
traced process and recorded alongside the project's -- measured on an
`import requests` workload, the freeze carries nine packages belonging to
roar. They cannot be separated afterwards: roar's copy of a package and
the workload's are the same file at the same path, so nothing -- path,
name, or dist metadata -- can attribute them. Subtracting by name once
stripped the workload's own tqdm and typing-extensions (P0-28), which is
why `roar_footprint_paths` abstains and the freeze over-includes instead.

#287 tried to fix the second cost by snapshotting sys.modules at the end
of bootstrap and subtracting it. That is measurably inert -- roar's
dependencies load lazily *after* the boundary -- while risking a real
false negative, so it was closed in favour of saying this plainly.

The comparison is against the interpreter the WORKLOAD would use, not
roar's own. That distinction is the whole check: under `uv tool` or pipx,
roar runs from its own venv and so always sits inside its own sys.prefix,
so comparing roar against itself reports every correctly isolated install
as shared -- nagging exactly the users who took the advice. Resolution
mirrors a shell's: active virtualenv, else conda env, else the first
python on PATH; unresolvable means stay quiet.

Verified live in both layouts rather than by assumption: roar copied into
a project venv warns; roar in its own venv with a project venv active
stays silent; and with no venv active, a tool install still stays silent
because the workload would run the system python.

Printed once at `roar init`, not per run: it is a property of how roar was
installed, and a per-run warning is noise people learn to skip. It rides
the existing hint machinery, so `roar config set hints.enabled false`
already silences it. Both uv and pipx are offered, with install routes,
since not everyone has uv.

Seven tests over the real layouts (pip-into-venv, tool-install with and
without an active venv, system install, conda), each verified to fail
against the naive roar-vs-its-own-prefix comparison. Detection cannot fail
the command; a cosmetic hint is never worth breaking `roar init` for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@christophergeyer
christophergeyer force-pushed the cg/warn-shared-venv-install branch from 8b6c9e2 to da73261 Compare August 19, 2026 15:56
@christophergeyer
christophergeyer merged commit 0afeddc into rc/0.4.4 Aug 19, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants