Author a new package from conda-forge or Spack#
This workflow turns a foreign package recipe into a canonical manifest, planned SBOM, Resolvo profile locks, conventional EasyBuild recipes, and a persisted build-evaluation campaign. It is the workflow used for conda-forge eOn and Spack QMCPACK fixtures.
Inputs#
Collect these inputs:
a conda-forge
meta.yaml~/~recipe.yamlor Spackpackage.py;one or more public product-profile TOML files;
an EasyBuild robot tree, with site overlays passed after upstream;
a stack-policy TOML file for preferred pins, locked pins, and exclusions.
positional SHA-256 values for source artifacts whose foreign metadata has only a VCS commit or tag.
Profile TOML is where installable product choices belong. Each profile emits a
separate .eb file. MPI/OpenMP toolchain options alone do not create a suffix;
an independently loadable ABI or feature variant does.
Inspect the foreign recipe#
eb-stack package inspect \
--source fixtures/foreign_ingest/conda_eon/recipe.yaml \
--format conda-forge \
--toolchain-name foss \
--toolchain-version 2026.1 \
--profile-config examples/profiles/eon.toml \
--out-dir /tmp/eon-inspect
Inspect package.plan.json and package.sbom.cdx.json. The parser preserves
source spans, dependency roles, conda selectors, Spack when= conditions,
variants, conflicts, requirements, and static build flags. Dynamic foreign
logic becomes a residual rather than an invented fact.
Inspection may report source:missing-sha256 for a commit-pinned Spack
release. A VCS commit does not determine the byte hash of the generated source
archive. Pass the reviewed archive hash to package plan with one
--source-checksum per source artifact; the planner does not invent or omit
packaging checksums.
For QMCPACK:
eb-stack package inspect \
--source fixtures/foreign_ingest/spack_qmcpack/package.py \
--format spack \
--toolchain-name foss \
--toolchain-version 2026.1 \
--profile-config examples/profiles/qmcpack.toml \
--out-dir /tmp/qmcpack-inspect
Define product profiles#
A profile layer can replace or extend the parser-derived defaults. The public
examples show the complete schema. A QMCPACK profile set commonly contains a
default MPI+OpenMP build and a separate -complex recipe:
schema_version = 1
[[profiles]]
name = "default"
default = true
versionsuffix = []
config_options = ["-DQMC_MPI=ON", "-DQMC_OMP=ON", "-DQMC_COMPLEX=OFF"]
[profiles.toolchain_options]
usempi = true
openmp = true
[[profiles.verification_commands]]
program = "bash"
args = ["-lc", "module load {module} && qmcpack --version"]
[[profiles]]
name = "complex"
default = false
versionsuffix = ["-complex"]
config_options = ["-DQMC_MPI=ON", "-DQMC_OMP=ON", "-DQMC_COMPLEX=ON"]
Verification placeholders are {module}, {package}, {version},
{profile}, and {versionsuffix}.
Put stack knowledge inside Resolvo#
Site or distribution pins are solver input, not a text rewrite after solving:
schema_version = 1
name = "foss-2026.1"
toolchain = { name = "foss", version = "2026.1" }
[[pins]]
name = "HDF5"
version_requirement = "==2.1.1"
mode = "preferred"
source = "site stack"
[[pins]]
name = "PyTorch"
version_requirement = "==2.9.1"
toolchain = { name = "foss", version = "2024a" }
versionsuffix = ""
mode = "preferred"
source = "distribution stack"
A preferred pin is favored when jointly feasible. Resolvo may choose another
compatible candidate and records the requested version, toolchain,
versionsuffix, selected identity, and fallback. A locked pin cannot fall back.
Omitting toolchain or versionsuffix leaves that part of the artifact
identity unconstrained. Candidate exclusions record known target/build
evidence and stay visible in the profile lock.
Plan the complete bundle#
eb-stack package plan \
--source fixtures/foreign_ingest/conda_eon/recipe.yaml \
--format conda-forge \
--toolchain-name foss \
--toolchain-version 2026.1 \
--profile-config examples/profiles/eon.toml \
--easyconfigs /path/to/easybuild-easyconfigs/easybuild/easyconfigs \
--easyconfigs fixtures/eon_foss_2026_1/easyconfigs \
--stack-policy examples/stacks/eon-foss-2026.1.toml \
--out-dir /tmp/eon
The command must produce a manifest, SBOM, one lock per requested profile, and
one recipe per profile. Run recipe format, recipe lint, and recipe check
against the upstream tree plus the bundle overlay.
eb-stack recipe format /tmp/eon/easyconfigs/e/eOn/*.eb
eb-stack recipe lint /tmp/eon/easyconfigs/e/eOn/*.eb
eb-stack recipe check \
--recipe /tmp/eon/easyconfigs/e/eOn/eOn-2.16.0-foss-2026.1.eb \
--easyconfigs /path/to/easybuild-easyconfigs/easybuild/easyconfigs \
--easyconfigs /tmp/eon/easyconfigs
Missing robot dependencies are real package work. Add their foreign recipe or an authored EasyBuild recipe and run the canonical planner again; do not create placeholder recipes with dummy checksums.
Route the build#
Keep reusable topology in a public base file and site details in a later layer:
eb-stack target list \
--config examples/targets/base.toml \
--config ~/.config/eb-stack/site.toml
eb-stack target doctor \
--config examples/targets/base.toml \
--config ~/.config/eb-stack/site.toml \
--target site-builder
The selected target decides transport, executor, runtime, and EasyBuild
workload. A control host can therefore stage over SSH, submit through Slurm,
run on the host or in Podman/Docker, and invoke the site’s EasyBuild command.
Use a runtime-specific EASYBUILD_INSTALLPATH, work_root, and tmp_root so
host-linked modules cannot leak into a container build. A shared
EASYBUILD_SOURCEPATH is safe for source archives.
Run the Hermes/OMP repair loop#
eb-stack campaign run \
--bundle /tmp/eon \
--config examples/targets/base.toml \
--config ~/.config/eb-stack/site.toml \
--target site-builder \
--state /tmp/eon.campaign.json
Hermes owns the campaign loop. OMP workers claim typed findings, repair the manifest/profile/recipe/target layer appropriate to the class, record evidence, and rerun the campaign. Build compatibility claims are not proof: configure, compile, link, test, install, and sanity failures stay empirical findings until the target build succeeds.
The endpoint is three separate claims:
resolves: all profile locks and recipes exist;
builds: every recipe succeeds through EasyBuild on the selected target;
binary-verified: every declared verification command succeeds.
Follow skills/new-package/SKILL.md for the exact campaign procedure and
human-owned PR handoff.