The host side of the evolving host.compute job surface lives here, together with the separate registry that the purpose-built remote-science services use to find a real GPU host. Heavy work leaves the machine one of two ways: through a discovered byoc:<id> provider, or over an ssh:<alias> connection the user already has. This is orchestration and transport code. There is no scheduler here, no GPU runtime, and no scientific model.
The Python host.compute SDK turns every call into a compute_<operation> Host RPC. HostDispatcher creates one ComputeManager per session on first use and maps ComputeError into a structured soft failure. The native compute_submit, compute_result, compute_cancel and compute_close tools expose a bounded slice of that control plane; the richer SDK compatibility calls reach the same manager.
For byoc:*, the manager looks for provider shims under skills/remote-compute-<id>/, stages a job archive, and runs the confined openai4s_compute_provider helper with credentials on stdin. For ssh:*, it shells out to local ssh/scp against a user-configured alias. Harvested files land below the configured data directory, in hpc/<job_id>/.
| File | Responsibility |
|---|---|
__init__.py |
Exports the two names the rest of the host needs: ComputeManager and the structured ComputeError. |
manager.py |
Both transports. It discovers BYOC provider Skills, routes byoc:* and ssh:*, refuses a submission once the session's concurrency limit is reached, stages inputs and the job templates, and tracks live jobs and warm sandboxes through poll, cancel, close and harvest. An alias an agent names has to be one the user actually offered — the registry, or their own ~/.ssh/config — and every ssh/scp argv is assembled in one place, so that guard is structural rather than remembered at each call site. Output from a machine we do not control is drained so the remote never blocks on write, but retained only up to a cap: a chatty login profile or a forced command otherwise had the whole per-command timeout to make the daemon allocate. The credential is picked out by the environment-variable names the provider declares, and it reaches the helper on stdin rather than through the environment. The helper's environment is otherwise the daemon's own, minus every name the helper's own scrub_secret_env would drop (credential-shaped names and the baseline secret prefixes) and the provider's declared secret_env names. That filter runs before exec, not only inside the helper, because a process can always read its own exec-time environment block and an in-process scrub does not change it. The helper is started in a session of its own: on macOS that is what makes the profile's process-info denies hold, so it cannot read the daemon's environment either. A staged input may name an Artifact version_id instead of a path: the manager stages only the frozen snapshot bytes the Host resolved for that version, refuses a version the Host did not resolve, and persists the declared versions on the job row so every later result carries them. The ssh transport takes no staged inputs at all — upload explicitly before submit. |
stage11.py |
Stage 11 product hooks, opt-in via OPENAI4S_STAGE11_DURABLE_REMOTE_COMPUTE: the flag itself, the first-access recovery projection over the durable jobs the lazy manager rehydrates when it is constructed, and the harvest Artifact provenance receipts that bind a verified manifest — remote environment, input versions, job receipt, per-file checksums — to exact workspace paths. A terminal re-poll's cached harvest deliberately yields no receipts, and nothing here resubmits. |
states.py |
The job vocabulary and its transition table, enforced when a status is written. unknown is deliberately live: the remote operation may or may not have landed, so it is rehydrated and reconciled rather than forgotten. A terminal state cannot be re-opened by a late probe — including by a write of the same status, because the write carries the evidence that established it, so two pollers that both read running would otherwise each commit their own manifest over the other's. |
manifest.py |
What a harvest actually produced: {path, size, sha256} per file plus one digest over the set, and the reconciliation of that record against the globs the job declared in outputs. A declared pattern matching nothing is why a job that exited 0 can still be failed — and the size/hash pair is the only thing that can see a transfer truncated at rc==0. A declaration may also ask for visibility: hidden or residency: remote; neither is counted missing, and a stay-remote pattern is excluded from the transfer rather than merely excused from the reconciliation. |
registry.py |
Remembers which SSH host aliases exist, which one is the default, and what fold/score_mutations-style capability metadata has been provisioned on each, written atomically to <data_dir>/remote_compute.json. Native registration probes the host before it records verification; a host seeded from the legacy environment variable may sit there unverified. is_known_alias is also the authorization side of the ssh transport: registered here, or present in the user's own ~/.ssh/config. It stores no SSH private keys and no provider tokens. |
safe_archive.py |
Enumerate-then-extract for a harvest arriving from a machine we do not control — used by both transports, since the bytes are attacker-shaped either way. Traversal, absolute paths, links, device nodes and decompression bombs are refused before a byte is written, and rejection is all-or-nothing: a partial extraction of a hostile archive is still a compromise. tarfile.extractall defends against none of it on the Python versions in scope. |
| Directory | Responsibility |
|---|---|
templates/ |
Shell templates staged into a BYOC job. They run the submitted command, handle the time and deadline limits, and package output and logs for harvest. See its README. |
submit validates the provider family, checks the concurrency count, and — for ssh:* — refuses a destination the user never offered. The job row is claimed before the remote call, so there is something to reconcile against however the submit ends.in.tar.gz from the wrapper, the command and the inputs, and calls the helper's create and submit operations. The submit carries the container's absolute expiry alongside the harvest margin and the term grace, so the wrapper's watchdog is actually armed: nothing on the host used to produce those values, and a container could be reclaimed mid-job, taking the results with it. An SSH submission creates a remote work directory and starts run.sh under nohup.result polls the exact job this session owns. On the BYOC path the helper's wait stages out.tar.gz; the SSH path builds its own archive of the work directory remotely and pulls it back. Both go through the same hostile-input-safe extractor and land under hpc/<job_id>/. The SSH work directory itself stays on the remote host — only the staged tarball is removed.cancel signals the remote process group and confirms it is gone, or terminates the BYOC sandbox. close terminates each job individually and marks it cancelled only on confirmation; anything unconfirmed stays live, keeps its slot, and is reported back by name. Because BYOC jobs share one sandbox per provider, a confirmed sandbox termination ends every live job riding it — including ones this handle never named.reconcile() reports those jobs and deliberately never resubmits — a job in flight may or may not be running, and guessing wrong costs either a duplicate charge or a lost result. What is still in-memory only: the warm byoc sandbox handle per provider, so a restart cannot reuse a warm container (the job that container is running is still recoverable through its receipt). registry.py persists the specialized SSH capability catalogue._commit_terminal writes the end state to the ledger before memory or any observer believes it, and does not swallow the failure: a lost compare-and-swap re-reads the row and reports what actually won, and any other write failure propagates rather than being reported as success. The row stays live in that case and reconcile keeps surfacing it, which is the safe direction — claiming a success the ledger never accepted is not.idempotency_key already on one of this owner's rows makes the second submit an error naming the winner, and the UNIQUE index catches the pair that raced past the pre-check. The success receipt — the sandbox id, or the remote pid/pgid — is persisted before memory believes the job is cleanly running; a dropped write degrades to unknown/submit_indeterminate rather than reporting a clean running over a row with no receipt, which is an orphan that bills with nothing left able to name it.result() is what probes the remote and harvests; a job nobody polls is never harvested.result, cancel and the per-job event stream all resolve through the same owner-scoped map, so a job id belonging to another session is indistinguishable from one that does not exist.compute_submit is approval-gated. Harvesting a result, cancelling, and closing deliberately do not ask a second time for a job that was already authorized. The richer direct compute_ssh/compute_scp compatibility methods still require an alias the user offered, but they are not in the native gate at all — approval of compute_submit must not be read as approval of them.security/byoc_confinement.py and passes the anchor the helper's own probe compares against; the helper checks from inside before it reads a credential and exits 71 without acting if the boundary does not hold. enforce fails closed on every op, not only at submit; auto degrades to the unconfined form visibly. What that boundary is not: the network is deliberately still reachable, because calling a provider's REST API is the helper's whole job. Credentials are selected by declared environment-variable name and sent on the helper's auth input, so a secret sitting in a name nobody declared can slip past name-based scrubbing.verified_at; the legacy OPENAI4S_FOLD_SSH seed and caller-supplied metadata may never have been checked. Resolving a capability says nothing about whether the host answers right now, so host/remote_science.py must check and fail honestly when the remote service is unavailable.provider.json and a provider.py. No SLURM, no Kubernetes, no general cluster scheduler is implemented here.