Skip to content

ump_spec.gates

module ump-spec

Gate evaluator: the POC stand-in for OPA/Rego (spec §15, §25.4).

evaluate(kind, transition, artifact_doc, context, mode) selects the gates in the catalogue (registries/gates/*.yaml) that apply to that artifact kind and transition (or operation= for non-transition hooks such as combine, calibrate, pool, approve, seal, export, agent_session), runs each gate’s registered Python predicate, and returns GateResult rows in the fixed apply order: hard stops, exclusions, fallbacks, routes, warnings, then info/computed and passes.

Gates degrade before they block. Only the eight hard stops stop by default; mode="strict" (or a gate listed in strict_gates) turns a Fall back outcome into strict_stop for gates whose strict_override is true. Strict affects only Fall back: Exclude and continue (EVIDENCE_EXCLUDED stays a note), Route, Warn and Computed outcomes are unchanged (spec §15). An unknown id in gate_ids or strict_gates is SCHEMA_INVALID. raise_for_stops leads with hard stops, then strict stops, each in gate catalogue order, and lists every stop in errors (spec §19). Gates without a POC predicate pass with an NOT_IMPLEMENTED_IN_POC info note and predicate="not_implemented_in_poc".

Hard stops fail closed (spec §15): on an operation inside a hard stop’s binding (HARD_STOP_BINDINGS), an input the gate needs that is missing, malformed or unverifiable is a failure, never not applicable.

Context keys read by predicates are listed in CONTEXT_KEYS; they are optional except where a hard stop’s binding needs them.

class

class GateContext

Fields

NameTypeDefaultDescription
gateGateDefinition
kindstr | None
transitionstr | None
operationstr | None
docdict[str, Any]
ctxdict[str, Any]
modeMode
Methods and properties (2)

threshold method

def threshold(self, name: str, default: Any = None) -> Any

init constructor

GateContext(
self,
gate: GateDefinition,
kind: str | None,
transition: str | None,
operation: str | None,
doc: dict[str, Any],
ctx: dict[str, Any],
mode: Mode,
) -> None

Source: packages/ump-spec/src/ump_spec/gates.py, line 107

class

class Check

Fields

NameTypeDefaultDescription
passedbool
messagestr''
applicableboolTrue
outcomeGateOutcome | NoneNone
fallbackslist[FallbackEntry]field(default_factory=list)
noteslist[Note]field(default_factory=list)
evidencedict[str, Any]field(default_factory=dict)
route_tostr | NoneNone
Methods and properties (1)

init constructor

Check(
self,
passed: bool,
message: str = '',
applicable: bool = True,
outcome: GateOutcome | None = None,
fallbacks: list[FallbackEntry] = list(),
notes: list[Note] = list(),
evidence: dict[str, Any] = dict(),
route_to: str | None = None,
) -> None

Source: packages/ump-spec/src/ump_spec/gates.py, line 124

class

class GateSummary

Fields

NameTypeDefaultDescription
stoppedbool
next_stateLiteral['checks_passed', 'checks_failed']
stopslist[GateResult]
exclusionslist[GateResult]
fallbackslist[GateResult]
routeslist[GateResult]
warningslist[GateResult]
fallback_entrieslist[FallbackEntry]
noteslist[Note]
route_tolist[str]
Methods and properties (2)

as_dict method

def as_dict(self) -> dict[str, Any]

init constructor

GateSummary(
self,
stopped: bool,
next_state: Literal['checks_passed', 'checks_failed'],
stops: list[GateResult],
exclusions: list[GateResult],
fallbacks: list[GateResult],
routes: list[GateResult],
warnings: list[GateResult],
fallback_entries: list[FallbackEntry],
notes: list[Note],
route_to: list[str],
) -> None

Source: packages/ump-spec/src/ump_spec/gates.py, line 1955

function

def predicate(*gate_ids: str) -> Callable[[Predicate], Predicate]

Register a predicate for one or more gate ids.

Source: packages/ump-spec/src/ump_spec/gates.py, line 142

function

def hard_stop_bound(gc: GateContext) -> bool

True when gc is an operation inside its hard stop’s binding, so missing input must fail.

Source: packages/ump-spec/src/ump_spec/gates.py, line 415

function

def differencing_risk(
aggregate: dict[str, Any],
released: list[dict[str, Any]],
floor: int,
) -> dict[str, Any] | None

The differencing risk of releasing aggregate after released (G-PRIV-03, spec §20), or None.

Inputs are {query, n, cells?: [{id, n}]} and assumed well formed (the gate checks shape first). Three rules, the first that finds a group below floor wins:

  • same_query: a repeat of a released query (rules.normalise_query) whose total differs by 0 < d < floor;
  • cell_resized: a cell released before whose size changed by 0 < d < floor;
  • set_overlap: a group of cells that the new aggregate, with any set of released ones, isolates. Pairwise checks are necessary and not sufficient, so the search runs over the whole set.

Clean-room connectors call this, so the rule lives only here.

Source: packages/ump-spec/src/ump_spec/gates.py, line 722

function

def differencing_words(risk: dict[str, Any]) -> str

Plain words for a differencing_risk result, naming its rule and how many people it could single out. A set_overlap found by the conservative check (exact: false) says so.

Source: packages/ump-spec/src/ump_spec/gates.py, line 759

function

def find_personal_data(rec: Any, ptr: str = '') -> list[str]

Pointers to fields that look like personal data (keys or email/phone-like strings).

Source: packages/ump-spec/src/ump_spec/gates.py, line 988

function

def is_write_or_run_tool(name: str) -> bool

Source: packages/ump-spec/src/ump_spec/gates.py, line 1031

function

def select_gates(
kind: str | None,
transition: str | None = None,
operation: str | None = None,
catalogue: dict[str, GateDefinition] | None = None,
) -> list[GateDefinition]

Gates that apply to kind at transition (target state) and/or operation.

Source: packages/ump-spec/src/ump_spec/gates.py, line 1858

function

def evaluate(
kind: str | None,
transition: str | None,
artifact_doc: dict[str, Any] | None,
context: dict[str, Any] | None = None,
mode: Mode = 'fallback',
*,
operation: str | None = None,
gate_ids: Iterable[str] | None = None,
strict_gates: Iterable[str] = (),
artifact_id: str | None = None,
artifact_version: int | None = None,
) -> list[GateResult]

Run the applicable gates and return results in apply order (stops first).

Source: packages/ump-spec/src/ump_spec/gates.py, line 1886

function

def summarize(results: list[GateResult]) -> GateSummary

Source: packages/ump-spec/src/ump_spec/gates.py, line 1982

function

def raise_for_stops(results: list[GateResult]) -> None

Raise UmpError when anything stopped (spec §19). The top-level problem is the most urgent stop: hard stops first, then strict stops, each in gate catalogue order. errors lists every stop. Hard stops keep their registered status (403 for privacy, approver and tool separation; 409 for integrity); a strict stop takes its code’s strict status (e.g. ESTIMAND_UNDECLARED 422), or 409 when the code has none.

Source: packages/ump-spec/src/ump_spec/gates.py, line 2011

function

def implemented_gates() -> list[str]

Source: packages/ump-spec/src/ump_spec/gates.py, line 2036

NameTypeValueDescription
ModeGateFailMode
CONTEXT_KEYSdict[str, str]{'today': 'date for use-by checks (default: today UTC)', 'source_type': 'sour...
NACheck(passed=True, applicable=False, message='not applicable')
PredicateCallable[[GateContext], Check]
PREDICATESdict[str, Predicate]{}
HARD_STOP_BINDINGSdict[str, dict[str, frozenset[str]]]{'G-PRIV-01': {'operations': _PRIV_BOUND, 'transitions': frozenset()}, 'G-PRI...Operations (and target states) on which each hard stop fails closed (spec §15). materialize binds the G-PRIV gates only under copy_policy: aggregates_only (a clean-room read).
OVERLAP_EXACT_MAX_GROUPS12Most small atoms (Venn atoms below the floor) the exact set-overlap search enumerates unions of (proposed). Past it the check is conservative but still only refuses when a small atom could be part of a newly isolated group (see _set_overlap).
OVERLAP_EXACT_MAX_WORK200000Most fraction updates the set-overlap basis may spend (proposed). Sparse histories (stars, chains, padded links) of 200 linked releases spend a few thousand; a dense history that would spend more falls back to the conservative region check, which refuses any small positive Venn atom of the linked part (exact: false).
WRITE_RUN_TOOL_REre.compile('^(draft_|run_|write_|create_|update_|delete_|approve|transition|s...