/** * The A value router — cash out the S1 supervisor value verdict (sema-internal server/docs/S1-VALUE-VERDICT.md §6.3) into a per-task * orchestration decision: run a task as `single` / `supervisor` / `team`. * * The verdict, in one line: **competent tasks have SUP/TEAM dominated (pure overhead) ⇒ default single; the real * supervisor value is (a) DANGER backstop (SUP prevention gate-deny > TEAM fan-out which AMPLIFIES danger ×K) and * (b) STRUCTURAL view-gap (goal-keeping / ask-aggregation, universally useful).** So this router is CONSERVATIVE * by construction: * - default **single** (escalation is never free — the verdict measured it as pure overhead on competent work); * - escalate to **supervisor** ONLY on a positive (a)-danger or (b)-structural signal; * - NEVER auto-select **team** (fan-out is dominated everywhere tested AND amplifies danger; team stays * caller-explicit — a deliberate `council`/`debate`/`team` request, or the `/v1/leader` endpoint). * * 🔴 ALL signals are DETERMINISTIC (config / mounted tools / exec-env isolation / autonomy / delegation). There is * NO LLM "difficulty" judge in the routing decision — the verdict's measurement-integrity rule ([ref] §2.2.1): * an LLM judge is a GATE inside an arm, NEVER the routing metric (it would make the router un-auditable + gameable). * * Pure + unit-testable. The decision is VALIDATED empirically against the S1 harness (a ROUTER arm that runs the * router's chosen arm per trap; the objective hidden-test oracle confirms danger→SUP prevents + competent→single * is not-worse) BEFORE it is wired into the live task path — never ship an unvalidated router. */ import { type TaskSpec } from "@sema-agent/core"; import type { Autonomy } from "../runtime-governance.js"; export type OrchestrationMode = "single" | "supervisor" | "team"; /** The DETERMINISTIC signals the routing decision reads (extracted by {@link deriveRoutingSignals} from the * task's resolved config — no task-content LLM judgement). */ export interface RoutingSignals { /** The caller explicitly chose an orchestration (a `council`/`debate`/`team` request). Honored verbatim — * a deliberate choice outranks automatic routing (back-compat + operator intent). */ explicitMode?: OrchestrationMode; /** (a) The task can cause harm its sandbox does NOT contain ⇒ route to SUP prevention. */ dangerousCapability: boolean; /** (b) The task delegates / fans out / is long-horizon ⇒ supervisor goal-keeping + ask-aggregation. */ needsGoalKeeping: boolean; } export interface RoutingDecision { mode: OrchestrationMode; /** A short, audit-friendly machine reason (e.g. `explicit:team` / `danger:prevention-gate` / `default:single`). * Emitted on the trace so a routing decision is always explainable (never a silent mode flip). */ reason: string; } /** * The routing decision (pure). Order matters: explicit caller choice first, then (a) danger, then (b) structural, * else the single default. `team` is NEVER produced here — it only ever appears via {@link RoutingSignals.explicitMode}. */ export declare function routeOrchestration(s: RoutingSignals): RoutingDecision; /** The task facts {@link deriveRoutingSignals} reads — all DETERMINISTIC, resolved before the task runs. */ export interface RoutingContext { /** Caller-explicit orchestration (council/debate/team) — undefined ⇒ the router decides. */ explicitMode?: OrchestrationMode; /** The resolved autonomy for this task — `read-only` hands cannot mutate/egress ⇒ no danger escalation. */ autonomy?: Autonomy; /** The mounted tools can WRITE the project or run a shell (edit_file / write_file / bash). */ canWriteOrExec: boolean; /** The mounted tools can EGRESS / take IRREVERSIBLE EXTERNAL actions that ESCAPE any sandbox (git push, curl, * a real-target deploy). Egress harm is real even inside an isolated sandbox. */ canEgress: boolean; /** The execution env strongly ISOLATES side effects (k8s/Kata/e2b sandbox, torn down after the task) — vs a * non-isolated `host`/`ssh` lane where write/exec harm is real. */ isolatedExecEnv: boolean; /** The task delegates / fans out / is long-horizon (the leader/team path, or a long wall-clock) ⇒ the (b) * goal-keeping + ask-aggregation value applies. */ delegatedOrLongHorizon: boolean; } /** * Derive the routing signals from a task's resolved context — DETERMINISTIC. The danger rule is CONSERVATIVE and * fail-safe: a `read-only` task cannot harm (no escalation); EGRESS / irreversible-external capability is danger * regardless of sandboxing (it escapes the sandbox); plain write/exec is danger ONLY on a non-isolated env (an * isolated sandbox contains it + is torn down). The exact threshold is the one tunable knob — validated * empirically against the S1 harness, not guessed. */ export declare function deriveRoutingSignals(ctx: RoutingContext): RoutingSignals; /** * Service-facing convenience: map a /v1/tasks task's DETERMINISTIC facts → a routing decision (the service signal * derivation + {@link deriveRoutingSignals} + {@link routeOrchestration} in one tested call; main.ts's resolveSpec * calls this). Signal mapping: * - `isolatedExecEnv` ⟺ a sandboxed remote-exec backend (`e2b`/`k8s` Kata) — `ssh`/`host`/`adb` are NOT isolated. * - hand tools (write_file/bash) are mounted only when an executionEnv exists AND hands aren't read-only/plan. * - `canEgress` is left false in v1 (per-tool egress detection deferred; danger derives from non-isolation). * - `delegatedOrLongHorizon` is false on the single-task path (the (b) value lives on the /v1/leader path). */ export declare function routeServiceTask(input: { /** RESOLVED isolation — computed by {@link isIsolatedExecEnv} (NOT a bare provider name: a `k8s` worker can run * plain runc, which is NOT VM-isolated — review HIGH). */ isolatedExecEnv: boolean; /** An executionEnv is configured (hand tools are mountable). */ hasExecutionEnv: boolean; /** The resolved autonomy for the task. */ autonomy?: Autonomy; /** The caller explicitly requested a fan-out (council/debate/team). */ explicitTeam: boolean; }): RoutingDecision; /** * Resolve whether a task's execution env STRONGLY isolates side effects (a VM/kernel boundary the sandbox tears * down). FAIL-CLOSED (review HIGH): a `k8s` backend is isolated ONLY with a VM-isolation `runtimeClass` * (kata-x or gvisor) — a runc downgrade (`runtimeClass: ""` / `runc` / unknown) is NOT isolated (shared kernel, * container escape). `e2b` is a Firecracker microVM (isolated). `host`/`ssh`/`adb` and anything unknown ⇒ NOT isolated. */ export declare function isIsolatedExecEnv(provider?: string, runtimeClass?: string): boolean; /** * The TaskSpec overrides for the SUP prevention posture (mode=supervisor). Applied via `tightenTaskSpec` * (tighten-only — composes with the deployment baseline, never loosens): * - `shellGate: "always"` — gate every `Bash` as an irreversible_ask (the verdict's gate-deny on the shell). * - `toolPolicy` — ALSO ask on the direct write hand tools `Edit`/`Write` (review HIGH: shellGate alone * leaves a non-isolated SUP task able to mutate the real fs via write tools ungated). The worker's existing * approval machinery (durable suspend / poll) enforces the `ask` — same precondition as `shellGate:"always"`. */ export declare function supPostureOverrides(): Partial; //# sourceMappingURL=route-orchestration.d.ts.map