Appearance
Iso1 >>> Package Management
Recommendation. Give each computational unit its own environment, managed by a language-agnostic, cross-platform package manager, conda or mamba. Specify the unit's dependencies in an
environment.ymlfile and pin them with conda-lock files generated per operating system and CPU architecture, so the environment can be recreated identically on any matching platform.
When this applies
This is the first isolation level for every unit in every study. It is sufficient as long as a unit's dependencies can be installed from conda channels. When a unit needs a complex build system, legacy software, or packages conda does not carry, move up to Iso2.
Why
An environment that was assembled by hand cannot be rebuilt later; this is one of the most common reasons published computations fail to reproduce. An environment.yml alone does not fix that, because it leaves package versions and all indirect dependencies unpinned, and because the same file can resolve to different packages on different operating systems and CPU architectures. Lock files close both gaps, and per-platform locks are what makes results numerically equivalent across the machines your collaborators actually use. Conda and mamba are also the package managers that the workflow tools in the Orchestration pillar support natively, so an environment defined this way can later be declared in a workflow without changes.
In practice
One unit, one environment. The unit's dependencies live in an environment.yml next to its code:
yaml
name: surrogate-training
channels:
- conda-forge
dependencies:
- python=3.12
- numpy
- scikit-learn
- h5pyConda is not a Python tool; the same file can declare R, C and Fortran libraries, compilers, and command-line tools, which is what makes it work for multi-language studies. Mamba is a faster drop-in replacement for conda, and recent conda versions use the same resolver internally, so the two are interchangeable here.
Creating the environment from this file (mamba env create -f environment.yml) works, but resolves versions at whatever moment it runs. Two collaborators running the same command a month apart get different environments. So we add conda-lock, which resolves the environment once and records every package, including every indirect dependency, at an exact version:
bash
conda-lock lock --file environment.yml \
--platform linux-64 \
--platform osx-arm64 \
--platform win-64This produces a conda-lock.yml covering each requested platform. Note the plural: packages resolve differently per operating system and per CPU architecture, so we lock each platform your collaborators actually use, including both osx-64 and osx-arm64 if Intel and Apple Silicon Macs are both in play. Anyone can then recreate the exact environment with:
bash
conda-lock install --name surrogate-training conda-lock.ymlCommit both the environment.yml (the human-edited intent) and the lock file (the machine-resolved truth). When the environment.yml changes, the lock must be regenerated, and forgetting to do so is the main failure mode of this setup. That maintenance is exactly what Iso4 moves into CI.
A note on alternatives: pixi and the built-in Julia package manager lock by default, without a separate tool. They are good choices for standalone projects, but the workflow managers covered under Orchestration do not yet support them natively in their environment directives, so for units that will join an orchestrated study, conda plus conda-lock remains the recommendation. Julia units in particular often end up containerised instead, since Julia is awkward to manage through conda.
Related
If a unit's dependencies cannot be expressed this way, containerise it (Iso2). Keeping locks current across platforms is CI work (Iso4). The environment you define here is what a unit's contract declares under Orchestration (Orch1).

