# Action admission Gate's action-admission API is a disabled extension boundary for deterministic checks around agent tool calls. It does not register new hooks or change current tool behavior by itself. The model is: ```text native attempt -> adapter contract -> enrolled policies -> resolved effect -> native effect -> receipt ``` An adapter may claim only capabilities proved for its exact native event, phase, target, and version. A policy may inspect one complete JSON-primitive candidate field and return one of five actions: - `abstain`: no judgment; - `allow`: the candidate passed an applicable check; - `deny`: block the native action; - `repair`: replace the complete owned field once, before execution; or - `observe`: record bounded evidence without claiming prevention. There is no executable policy discovery. The caller constructs an `AdmissionKernel` with an explicit policy collection. Enrollment captures each validated descriptor as the policy's immutable authority record; replacing a policy object's later `descriptor` attribute cannot change its class, applicability, vocabulary, ownership, or override status. ## Capability contract Adapters advertise capabilities separately. A hook matcher or notification is not proof that the host can block or replace a call. | Capability | Meaning | | --- | --- | | `pre_admission` | The event runs before the native action. | | `input_complete` | The candidate contains the complete field value. | | `target_identity` | The adapter can identify the native target. | | `deny` | A denial prevents native execution. | | `repair` | The host executes the replacement and never the original. | | `feedback` | The host can show a bounded diagnostic to the agent. | | `post_observe` | The adapter can observe a completed action. | | `result_fields` | The post event exposes proved, allowlisted result fields. | | `retry` | The host owns a bounded retry mechanism. Gate does not invoke it. | Requested and enacted actions are distinct receipt fields. A pre-execution denial requires direct evidence for `pre_admission`, `input_complete`, `target_identity`, and `deny`. A repair also requires `repair`. A post-execution observation requires `post_observe`, `result_fields`, and `target_identity`; no post event can report a prevention effect. Missing proof yields `adapter.capability_missing`. A direct adapter that can deny but cannot repair turns a requested repair into a denial, so the agent can correct the input and retry. Gate never reports an unavailable effect as enforcement. ## Resolution Policies run in stable identifier order. A required deterministic failure requests denial; an optional failure is a visible abstention. Semantic policies may only observe or abstain, even when marked required: semantic uncertainty, failure, timeout, or invalid output never acquires denial authority. Each descriptor enrolls a static reason-code vocabulary and bounds candidate and diagnostic bytes. Its `overrun_threshold_ms` is a post-return measurement threshold, not an execution deadline. The synchronous v1 kernel records an overrun only after policy code returns; it cannot preempt a blocked policy. Enrollment therefore remains limited to reviewed, in-package, terminating code. The attempt deadline likewise prevents a policy from starting late and detects a return after the deadline, but cannot interrupt an evaluation already in progress. A repair owns one complete candidate field. Identical replacements may coalesce, while different replacements, undeclared ownership, an invalid digest, or a second repair round request denial. Repair conflicts, rejected repairs, and second-round repairs are kernel safety denials: their binding includes the contributing proposal digests and kernel rule, and they are never overridable. The repaired candidate is evaluated once more before the adapter may enact it. No successful decision is cached across attempts. Receipts include adapter and event identities, requested and enacted actions, and candidate and proposal digests. Policy reason codes must come from the descriptor's static enrollment; malformed field types or dynamic codes become bounded kernel failure codes. Receipts do not include candidate values, recovery text, feedback text, override actors, or override reasons. Kernel-generated failure rules remain valid static codes even when a policy ID uses the maximum length; an overlong readable rule is replaced by a content-derived `policy.failure.*` code. An attempt may also bind one immutable `PrimitiveSchema`. Its complete metadata and digest enter the attempt digest, while the receipt retains only that outer digest. Gate rejects stale schema metadata before policy evaluation. The v1 schema vocabulary is deliberately limited to bounded integers and booleans; richer host schemas remain outside this protocol. ## Overrides An override applies only when the adapter enacted a denial. It cannot turn a requested denial that degraded to abstention into allow, and Gate does not consume authority on that path. Constructing an `Override` does not confer authority. The caller must supply an `OverrideAuthority` backed by its authenticated operator channel. Gate validates the binding first and captures the authority's validated static identity once; the same captured identity is used in the receipt even if mutable authority state changes during authorization. The authority then authenticates the actor and reason and atomically consumes the override ID. It must return `authorized`, `unauthorized`, or `reused`. Gate rechecks both override expiry and the attempt deadline after the authority returns; a slow call may consume the identifier, but cannot authorize stale state. An override must be unexpired, reasoned, and bound to all of the following: - attempt digest; - denied-policy digest and exact rule IDs; - adapter ID; - session ID; and - an authenticated actor and reason held by the authority. The denied proposals remain in the decision and receipt. A reused or foreign override does not change the denial. A descriptor may mark a core rule non-overridable; no override can waive such a proposal. A successful receipt records the authority ID plus SHA-256 actor and reason digests, never their raw text. ## Harness evidence matrix This table records the current narrow evidence boundary. It does not promise that the new admission API is registered on any host; registration requires a separate adapter probe and activation decision. | Harness surface | Current proved effect | Admission status | | --- | --- | --- | | Claude `PreToolUse` on selected nested-launch tools | Direct deny in the existing superheavy hook | Adapter not yet wired | | Codex `PreToolUse` on `spawn_agent` | Direct deny in the existing superheavy hook | Adapter not yet wired | | Claude or Codex write/edit tools | No complete-candidate repair proof in this wave | Unavailable | | Gemini tool events | No exact installed-version probe in this wave | Unprobed | | Factory Droid, Cursor, Kimi, Antigravity, ZCode | No proved pre-execution prevention contract | Advisory evidence only | | Vix | Current adapter is explicitly non-blocking | Advisory only | | OpenCode and Kilo | No projected Gate hook surface | Unsupported | Unicode, bulletin, and argument-regularization policies must remain disabled until an adapter proves the exact target, complete candidate, pre-execution timing, and requested native effect. Generic Markdown rewriting remains a Corpus Controlled Prose responsibility. ## Python surface ```{py:currentmodule} gate.admission ``` ```{eval-rst} .. autoclass:: AdmissionKernel :members: admit .. autoclass:: Policy .. autoclass:: PolicyDescriptor :members: create .. autoclass:: Attempt .. autoclass:: PrimitiveSchema :members: create .. autoclass:: Proposal .. autoclass:: OverrideAuthority .. autoclass:: Decision .. autoclass:: Receipt :members: as_dict ```