Repository navigation
lab: worker job interface (local and SSH transports) - #21
Merged
Merged
Conversation
srt cannot jail GPU code on Linux: no device passthrough, and each jail gets its own network namespace, so a served engine is unreachable from the clients. On Linux, agent code (tests, profilers, served engines) now runs in one container per command: NVIDIA runtime, --network none, read-only root, non-root user, no capabilities, cpuset leaving cores for the clients. A served port reaches the host through a socat bridge over a unix socket. srt stays on macOS; LAB_JAIL overrides. vm-setup.sh installs docker + NVIDIA Container Toolkit, builds lab-jail, and checks the GPU inside it. lab/RUNTIME.md is the controller/worker design this starts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A leftover process on the GPU could slow a bench, equiv or submit or stop the engine from starting, and the ledger recorded that as the snapshot's result; a contaminated base measurement was cached and skewed every later submit. serve.Served now refuses to launch while any process holds the GPU (GpuBusy, nothing launched) and polls the GPU's processes every second while serving; anything outside the engine's own process tree (descendants, or the container's processes) makes exclusive() raise Contaminated. bench/equiv/submit/baseline record verdict refused or contaminated with gpu_processes as facts; a contaminated run is never evidence, never cached as the base, and is caught before the holdout guard spends a query. lab.validate's noise bands get the same check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The GPU work behind test, profile/trace/kernel/hostprof, bench, equiv, submit and the base measurement now runs as worker jobs (lab/worker.py: test, measure, equiv, profile). A job takes input trees and JSON args, writes an out dir and returns JSON; the tools keep the policy, the ledger and the budget and call self.worker. LAB_WORKER=local (default) runs jobs in process, as before. LAB_WORKER=ssh runs them on the lab.vm VM: each tree goes by content hash at most once (has/put), the worker re-hashes a fresh copy before every job and refuses a mismatch, and the out dir comes back as a tar. GpuBusy, Contaminated, NotReady and ValueError are raised again on the controller. equiv ships the snapshot's earlier answers with the job, so a second equiv never re-rolls the gate (it already did not, in process). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…10-09) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he dependency build step (approved 2026-10-09) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # lab/README.md
# Conflicts: # lab/evaltools.py
# Conflicts: # lab/evaltools.py # lab/proftools.py
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 #20, which is stacked on #19. Retarget once those merge.
What
lab/worker.py: the job interface fromlab/RUNTIME.md, built for the measured jobs.testtree{lint, tests}measuretree{results, ready_s}passiveequivtree,reference,priorequiv.json,equiv.outputs.jsonl, passive dataprofiletree{returncode, output, …}bench,submitand the base measurement sharemeasure.profile,trace,kernelandhostprofshareprofile; the instrument definitions moved into a pureproftools.instrument(kind, args).self.worker. Ledger records and the agent-facing text are unchanged.LAB_WORKER=local(default) runs jobs in process.LAB_WORKER=sshruns them on the VMlab.vmnames:has,put);GpuBusy,Contaminated,NotReadyandValueErrorare raised again on the controller.Kept on purpose
Calling
equivagain on the same snapshot reuses its earlier answers; it never re-rolls the statistical gate. In process this came from the answers file living in the run dir. With a fresh out dir per job it would have been lost, soequivnow ships those answers as thepriorinput. A new test marks the stored answers and checks the mark survives a secondequiv; it fails without the fix.Tested
Remoteend to end through a local shell running the samepython -m lab.workerCLI that SSH would run:GpuBusy, with its facts, crosses from a fakenvidia-smi;NotReadycrosses, and the engine log still comes back;putis refused;putwhose content doesn't match its hash is refused.LAB_WORKER=sshagainst a real VM.Not in this PR
The agent's side on the worker: the agent container with freeze-before-measure, the API-key proxy, and the
agent/exec/snapshot/restore/factsjobs.🤖 Generated with Claude Code