UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

49 lines (48 loc) • 3.61 kB
/** * F-012 L2 — the ENGINE-INTERNAL ask-class envelope. * * An `ask` verdict's SEMANTIC CLASS decides whether a deployment-declared sandbox may auto-admit it * (the ruling: a declared sandbox admits everything inside it — the boundary crossings park to a * human, escape prevention belongs to the sandbox, not to engine re-policing). The class deliberately * lives OUTSIDE the public `PermissionResult`: a decision object is caller-supplied data, and a * self-reported "this ask is sandbox-local" field would be the same trust hole as the * `decisionReason:"safety"` self-declaration this codebase already refuses. Instead, BUILT-IN policy * factories register their instances here (private WeakMap brand — nothing a deployment policy can * self-declare by shaping its return value), and everything unregistered reads as `unknown`. * * Classes and their dominance (STRICT — merge keeps the strongest; only an all-`sandbox_local` set * may auto-admit): * - `sandbox_local` — an engine-authored "confirm a potentially destructive LOCAL action" ask * (name/pattern confirmation lists). Sandbox containment answers it. * - `external_authority` — an ask whose whole point is real judgment (the safety-rule policies with * `requiresRealApproval`); containment answers nothing about it. * - `hook` — a screening-face ask (a deployment's PreToolUse verdict folded to policy * form); the face's authority is the deployment's, not the sandbox's. * - `mandate` — an ask bound to durable-park semantics (inherited durable mandate / * approver-unavailable float); it must reach the park untouched. * - `unknown` — everything unregistered, every deployment policy. Fail-closed: never * admitted. */ export type AskClass = "sandbox_local" | "external_authority" | "hook" | "mandate" | "unknown"; /** * Brand a built-in policy instance with its ask class (engine factories only — not exported from the * package). The `check` binding is LOCKED as a non-writable, non-configurable DATA property before the * policy is returned (falsification-style round 4, HIGH): reading `policy.check` and INVOKING it must * name the same callable, atomically. A plain `===` re-read was TOCTOU-able by an accessor — a getter * could return the branded function to `policyAskClassOf` and a deployment ask to the gate's * invocation. Locking the property makes the callable un-swappable and un-redefinable, so the class * travels with the exact decision function. An `check` that is ALREADY accessor-backed (or a frozen * object we cannot lock) is refused branding — it reads back `unknown` (fail-closed), never trusted. */ export declare function brandPolicyAskClass<T extends { check: unknown; }>(policy: T, cls: AskClass): T; /** The registered class of a policy instance — `unknown` for anything unregistered, whose `check` is * no longer the locked data value, or whose `check` became accessor-backed (fail-closed: a * replaced/decorated/getter-shadowed decision function is not the branded one). Reads the property * DESCRIPTOR's value (never invokes a getter), so the check is atomic with what the gate will call. */ export declare function policyAskClassOf(policy: (object & { check?: unknown; }) | null | undefined): AskClass; /** The strongest class in a set (strict dominance — any non-`sandbox_local` member dominates). */ export declare function dominantAskClass(classes: readonly AskClass[]): AskClass;