@sema-agent/core
Version:
Stateless, task-oriented AI agent core
85 lines (84 loc) • 6.26 kB
TypeScript
/**
* Gate-1 — oracleIsolation (design/77 §1): the CORE SEAM + assertion for the out-of-process grader boundary,
* the 4th auto-promote gate. The whole auto-promote tier is **mandate-OFF** (design/77 §5/§7); this file only
* makes the seam EXIST so that auto-accept (`fixed`) becomes implementable once the SERVICE supplies the real
* isolated grader environment (an E2B/Kata container). SAFE-tier stays `candidate_only` regardless.
*
* **What core owns vs what the service owns** (mirrors {@link import("./remote-env.js").RemoteExecutionEnv} —
* core owns the seam shape; service owns the backend):
* - CORE: the {@link GraderEnv} provenance contract, the {@link assertOracleIsolation} assertion (3 fail-closed
* checks), and the {@link OracleIsolationVerdict}.isolationClass tiering that CAPS a non-isolated grader at
* `candidate_only` (never auto-accept).
* - SERVICE: the actually-isolated grader env (E2B microVM with `capabilities.isolation === true`), minted by
* the trusted control plane and handed to the repair loop as its grader env (the engine has no seat for it).
*
* 🔴 **Honest residual (design/77 §1 Residual + §9):** the bash write-probe is point-in-time and
* necessary-not-sufficient — core, running *inside the worker*, cannot prove a mount is truly immutable (it
* only observes that one write failed once; a candidate can `mount -o remount,rw` after the probe). And
* `capabilities.isolation` is self-declared by the adapter (a lying adapter can claim `true`). The REAL
* protection is the OUT-OF-PROCESS structural boundary (check B) on a control-plane-provisioned adapter — which
* is exactly why auto-promote stays mandate-OFF until the deployment contract is verified end-to-end (Slice-3).
*/
import type { ExecutionEnv } from "../internal/harness-types.js";
/**
* The verdict of {@link assertOracleIsolation}. `protected` is the fail-closed AND of all three checks
* (identity ∧ structural-class-acceptable ∧ write-probe). `isolationClass` is the load-bearing tiering that the
* (OFF) auto-accept path consults:
* - `"out_of_process"` — the grader is a real isolated sandbox (a remote env with `capabilities.isolation ===
* true`). ONLY this class is eligible for auto-accept (still mandate-OFF).
* - `"in_process_probe_only"` — the grader is non-remote or non-isolated; the bash write-probe is the only
* signal and it is necessary-not-sufficient → this CAPS the run at `candidate_only`, NEVER auto-accept (the
* 2-of-3 asymmetry, design/77 §1/§6: the oracle axis's real protection is the out-of-process boundary).
*/
export interface OracleIsolationVerdict {
protected: boolean;
isolationClass: "out_of_process" | "in_process_probe_only";
/** Set when `protected:false` (or when the class is downgraded) — the fail-closed reason, for observability. */
reason?: string;
}
/**
* The isolated grader environment, provisioned by the trusted control plane. `provenance` is settable ONLY by
* the trusted control plane that mints the grader env — it is NEVER reconstructed from
* worker-visible state (a worker that could mint a `{provenance:'control_plane'}` object would defeat the whole
* gate). `immutableOraclePaths` are the paths the oracle/spec is supposed to live behind (e.g. a hidden held-out
* test dir) that the worker must not be able to corrupt; the bash write-probe (check C) targets them.
*/
export interface GraderEnv {
/** The isolated env the oracle grades in (service-provisioned; a {@link import("./remote-env.js").RemoteExecutionEnv} in production). */
env: ExecutionEnv;
/** Paths the oracle must be protected behind — probed for writability through the WORKER's bash circumvention surface. */
immutableOraclePaths: string[];
/** Provenance brand — ONLY the control-plane factory sets this. Never derived from worker state. */
provenance: "control_plane";
}
/** Options for {@link assertOracleIsolation}. */
export interface AssertOracleIsolationOptions {
/** Abort the write-probe(s); an abort/timeout during the probe is fail-closed (protected:false). */
signal?: AbortSignal;
}
/**
* Assert that the grader env is isolated from the worker env so a positive oracle verdict is trustworthy
* (design/77 §1, the 4th auto-promote gate). THREE fail-closed checks — ANY failure ⇒ `protected:false`:
*
* **(A) IDENTITY** — `grader.env !== workerEnv` (reference inequality); when BOTH are remote envs, also require
* distinct `workspaceHandle().sandboxId`. A grader that IS the worker env (or the same sandbox) is grading in
* the very env the worker can corrupt.
*
* **(B) STRUCTURAL CLASS (the real protection)** — when `grader.env` is a {@link import("./remote-env.js").RemoteExecutionEnv}
* with `capabilities.isolation === true` ({@link isIsolated}, fail-closed default false) → `isolationClass =
* "out_of_process"` (the only class the OFF auto-accept path may consider). A non-remote / non-isolated grader →
* `"in_process_probe_only"`, which CAPS the run at `candidate_only` — never auto-accept. Note: a non-isolated
* grader is NOT itself a `protected:false` (the probe can still pass and the run can still be a legitimate
* `candidate_only`); the class is what gates auto-accept (the 2-of-3 asymmetry).
*
* **(C) BASH WRITE-PROBE (necessary-not-sufficient, cheap early signal)** — for each `immutableOraclePath`, run
* a write probe through the WORKER env's `exec` (the bash circumvention surface — see {@link probeCommand}), against
* the path canonicalized via {@link canonicalizeTarget}. The probe PASSES only if the write returns a non-zero
* exit code or an exec error (read-only mount / permission denied / not supported). Any SUCCESS (RC 0) ⇒ the
* oracle dir is writable from the worker ⇒ `protected:false`. A probe THROW / abort / timeout ⇒ fail-closed
* (`protected:false`).
*
* The verdict is fail-closed: the function itself never throws — a thrown probe is caught and mapped to
* `protected:false` (so a flaky env can't turn into a silent pass).
*/
export declare function assertOracleIsolation(workerEnv: ExecutionEnv, grader: GraderEnv, opts?: AssertOracleIsolationOptions): Promise<OracleIsolationVerdict>;