nemo_gym.data.tasks.harbor.verifier_env
nemo_gym.data.tasks.harbor.verifier_env
Harbor’s separate-verifier rules.
Which environment the verifier runs in, the verifier table or a copy of the task environment, whether tests/ is a build context of its own, which top-level keys, sidecars and main-service keys a tests/docker-compose.yaml may declare (and which such files cannot be read at all), and the two refusals the loader raises when a separate verifier has no image and no definition. The loader and the build planner both read these rules.
Module Contents
Functions
Data
VERIFIER_COMPOSE_TOP_LEVEL_KEYS
API
root is the dataset folder whose built-images.json the loader read (see _build_required).
The services mapping of the task’s tests/docker-compose.yaml; {} without the file, or for one that
does not parse or has no services mapping (a file the loader refuses first, verifier_compose_refusal).
Harbor’s refusal of a separate verifier environment with nothing to run: its environment dir is always
tests/ (_verifier_env_build_context in trial.py), checked by require_agent_environment_definition.
The environment a separate verifier runs in, as Harbor resolves it, or None in shared mode.
Harbor’s resolve_effective_verifier_env_config (verifier_mode.py at v0.22.0) for a single-step task:
[verifier.environment] when the task declares one, else a copy of [environment], so a task that only says
environment_mode = "separate" grades in an environment shaped like the agent’s, docker_image included.
The folder Harbor starts a step’s separate verifier environment from (_verifier_env_build_context with a
step in trial.py at v0.22.0): steps/<name>/tests/ when that folder exists, else the task’s tests/.
The environment a step’s separate verifier runs in, as Harbor’s resolve_effective_verifier_env_config
resolves it with a step: [steps.verifier.environment], else [verifier.environment], else a copy of
[environment]; None when the step verifies in shared mode.
"separate" or "shared" for one step, as Harbor’s resolve_step_verifier_mode (verifier_mode.py at
v0.22.0) resolves it: the step’s explicit [steps.verifier].environment_mode, else separate when the step
declares a [steps.verifier.environment], else the task’s own mode (HarborTaskConfig.is_shared_verifier).
Steps of one task may resolve differently.
The folder Harbor builds the separate verifier’s image from, tests/, when it builds one; else None.
Harbor starts the separate verifier’s environment with tests/ as its environment dir
(_verifier_env_build_context in trial.py at v0.22.0) and the effective verifier environment as its config
(effective_verifier_environment). Its Docker environment then uses the config’s docker_image when there
is one and otherwise runs docker compose build on tests/Dockerfile (should_use_prebuilt_docker_image,
start in docker.py), whatever that Dockerfile holds: a FROM plus RUN file is built, not overlaid. So:
shared mode, a declared or inherited docker_image, or no tests/Dockerfile means no build. Without the file
and without an image Harbor refuses the task (require_agent_environment_definition on tests/, which is
always its verifier environment dir: there is no fallback to environment/), and so does load_task.
Prepare plans one build entry per returned context (nemo_gym.data.tasks.harbor.image_build.plan_builds) and the
loader reads its record. A multi-step task whose steps verify separately builds tests/ for the steps that
declare no image and start from it (verifier_build_environment), whatever the task’s own mode.
The effective verifier environment whose settings Harbor’s build of tests/Dockerfile sees, or None
when nothing builds from tests/: the task’s own (effective_verifier_environment) when it declares no
docker_image, else the first step’s whose separate verifier declares none and starts from tests/
(step_verifier_build_context; a step with a tests/ folder of its own starts from that folder, which
this server does not build, and the loader refuses such a step). Steps that would build tests/ under
different environments share the first one’s settings here, where Harbor builds once per step.
The keys of main in the task’s tests/docker-compose.yaml other than VERIFIER_MAIN_KEYS (other
than PREBUILT_VERIFIER_MAIN_KEYS when prebuilt: the effective verifier environment names a
docker_image, so nothing builds from tests/, and a pull_policy of build counts too), in file
order; [] without the file or without a main mapping.
Harbor stacks that file on its verifier template for the build and for up (_docker_compose_paths in
docker.py at v0.22.0), so environment, env_file, volumes, command and every other runtime key of
main reach the verifier’s container: a test.sh that reads CHECK_MODE from main.environment sees it
there, an image beside a prebuilt verifier replaces the declared image Harbor’s template names
(${PREBUILT_IMAGE_NAME}), and a build section there has Harbor’s up build tests/Dockerfile under
the declared name, always with pull_policy: build (see VERIFIER_MAIN_KEYS). This server starts the
separate verifier as a single sandbox from the effective verifier environment of task.toml and the verifier
image alone, and reads the file for the build section and pinned image of a main it builds only, so such
a task would grade differently from Harbor without a word. It is refused instead, like one with verifier
sidecars: by load_task and, before any build, by ImageBuilder.build_many.
Why the task’s tests/docker-compose.yaml is not the file verifier_compose_sidecars and
verifier_compose_main_overrides read, as the loader’s message, or None when it is (or there is none).
Those readers see the file’s own services mapping and nothing else, so what they cannot see must not reach
Harbor’s verifier either. Harbor stacks the whole file on its verifier template (_docker_compose_paths in
docker.py at v0.22.0) and compose up applies every top-level key of it to the verifier’s project, so only the
keys this server reads or that cannot shape the verifier’s container pass (VERIFIER_COMPOSE_TOP_LEVEL_KEYS
and x- extension fields) and any other is refused by name. A top-level include merges the included files’
services into the project before the stacking, so main.environment or a build section written in an
included file reaches Harbor’s verifier container as if written here, while this server reads services: {}
and grades in the declared image without a word (validate_task_compose refuses include for a Dockerfile
build the same way; this is the loader’s refusal, for every separate verifier, prebuilt ones, which that
validator never sees, included). A top-level networks reconfigures the project’s default network, the one
Compose attaches main to because neither of Harbor’s templates gives it a networks or network_mode key
and, under Harbor’s default public policy, no egress overlay does either: default: {internal: true} grades
Harbor’s verifier without egress (driver_opts, ipam, enable_ipv6 likewise) while this server’s single
sandbox grades with it. Top-level volumes, configs and secrets are inert until a service references
them, and a reference on main is a key verifier_compose_main_overrides refuses, but the class is closed
rather than judged key by key, since each is a project setting the readers never see. A file that is not valid
YAML or not a mapping, or whose services is not one, fails Harbor’s compose up (and Harbor’s own reader of
the file, _egress_controlled_service_names in docker.py, parses it with yaml.safe_load), so the trial
errors under Harbor where the readers above would see {}; refused as validate_task_compose refuses it. An
empty file is an empty mapping, as it is there.
The services other than main that the task’s tests/docker-compose.yaml declares, in file order; []
without the file, or for one that does not parse or has no services mapping (verifier_compose_refusal
names such a file, and a top-level key other than services, first).
Harbor’s separate verifier is a whole Docker environment over tests/: it stacks that Compose file on its build
or prebuilt template (_docker_compose_paths in docker.py at v0.22.0), builds every service with a build
section and starts them all with up, image or built, prebuilt main or not. This server starts the
separate verifier as a single sandbox, so a task that declares any such service is refused: by
load_task and, before any build, by ImageBuilder.build_many. A main-only file (cadir’s and
arc-crm-6’s shape) is read for main’s build section, and its image when prepare builds the verifier; a
runtime setting on main (every key of arc-crm-6’s file: network_mode, pids_limit, security_opt,
cap_drop) is refused the same way (verifier_compose_main_overrides).