Execution Decision Model¶
ADK governs arbitrary executable actions — a ROS 2 cmd_vel publish, an AI agent tool call, a
Kubernetes scale operation — with one primitive. The domain lives in the signed manifest and in
pluggable providers; the core runtime is domain-neutral.
Pipeline¶
Proposed Action
↓
Policy Evaluation (Rego → Outcome + optional verdict/authorized_action/transformation)
↓
Manifest-defined Verdict (deployment vocabulary: CONSTRAIN, SANITIZE, CAP, …)
↓
Runtime-defined Effect (finite: pass_through | replace | reject)
↓
Provider Action Transform (optional, deterministic, domain-owned)
↓
Authorized Action (exactly one, for an executable decision)
↓
Enforcement Adapter (mechanical — no discretion)
↓
Execution
↓
Enactment Receipt (proposed → authorized → enacted; faithfulness verified)
Decision precedence¶
A verdict transforms an already-allowed action; it can never elevate a denied or deferred one. On
any non-Allow outcome the verdict and reason codes are recorded as audit metadata only and no
authorized action is surfaced.
Constraint ceilings¶
The operator’s manifest is the outer safety envelope: it caps the inputs a policy passes to a
transformation (action_transformations.constraint_ceilings). Because a policy can compute an input
from live data, the cap is enforced at decision time (where the concrete value exists); a literal
over-ceiling input in the policy is additionally rejected at bundle load. Ceilings are
constraint-kind-aware — a field is capped only where the provider declares it a numeric maximum
(ConstraintMax); unsupported kinds (a floor like a clearance threshold, an enum, an unknown field)
fail closed rather than blindly applying min(requested, ceiling). Capped fields are recorded on the
decision (transformation_constraints_applied) for audit.
Audit chain¶
Every enforced decision records: proposed action + digest → verdict → effect → selected transformation + provider id/version + inputs + constraints applied → authorized action + digest → enacted action + digest → faithfulness result / deviation → policy ref + manifest ref. This proves proposed → authorized → enacted end-to-end, across any domain.
Faithfulness is verified by comparing the canonical authorized action against the adapter’s
reported enacted action — generic, domain-free. An adapter that can only report a transport-
serialized payload (e.g. the ROS bridge’s CDR bytes) is decoded via a provider-registered action
codec (actiontransform.Codec — CodecID/Version/Supports(schema)/Encode/Decode), so the
encode + enactment paths serialize/deserialize without importing any domain transport package
(INV-EDM-3); an unknown schema yields an unverifiable-but-recorded receipt rather than a false verdict
on decode, and fails closed (ErrNoCodec) on a serialization-requiring encode. The codec is one
extensibility seam (#1347): a deployment governs a new actuator message type on the typed path by
contributing a Go codec, with no change to the generic runtime.
Actuator schemas (v1.9)¶
The optional actuator_schemas manifest block lets an operator declare, per actuator message
schema, the runtime’s knowledge of that message type — closing two follow-ups without an ADK code
change:
Field layout (#1347) — an ordered list of CDR fields (
{field, type}, dotted paths + fixed-size primitives). A domain-neutral layout codec (runtime/layoutcodec) encodes/decodes the exact RTPS CDR wire shape the hand-written codecs use (4-byte LE encapsulation header + size-aligned fields), so a message type ADK ships no Go codec for is still decodable on the faithfulness path. The enactment verifier consults a declared layout when no hand-written codec owns the reported bytes’ type, keeping the same decoded / malformed / not-owned contract. This removes the hardcoded{Twist, PoseStamped}limit: an operator adds a fixed-layout message (Ackermann, a custom Twist variant) by declaration alone.Validation contract (#1341) —
required/allowedfield paths + numericranges. The runtime validates the authorized actuator command against this contract (not merely for JSON-serializability): a policy cannot authorize an out-of-range or malformed command. The check runs fail-closed for both provider-generated (against the transformation’soutput_schema) and policy-direct authorized actions (keyed off the command’s messagetype).
Both are gated on an explicit schema_version ≥ 1.9 (an older runtime that can’t enforce a declared
contract / decode a declared layout must refuse the bundle, not silently ignore it).
Invariants¶
INV-EDM-1 — Verdict vocabulary is manifest-defined; the runtime hardcodes no domain verdict names.
INV-EDM-2 — Enforcement effects are runtime-defined and finite.
INV-EDM-3 — Transformation implementations are provider-defined and domain-isolated; the generic core imports no provider.
INV-EDM-4 — A transformation may only narrow or replace an already-allowed action.
INV-EDM-5 — A denied or deferred action is never elevated by a verdict or transformation.
INV-EDM-6 — Exactly one authorized action exists for an executable decision.
INV-EDM-7 — Adapters enact exactly the authorized action and have no transformation discretion.
INV-EDM-8 — Unknown verdicts, effects, transformations, providers, schemas, or malformed provider output fail closed.
INV-EDM-9 — The signed manifest binds the decision vocabulary, effects, providers, versions, schemas, and constraints.
INV-EDM-10 — Audit data proves proposed action → authorized action → enacted action.
Compatibility¶
The graded-verdict / maneuver naming that preceded this model never shipped to a release (it lived
only on the #1310 epic branch), so the generic model is a clean rename with no legacy aliases —
the manifest carries execution_decisions + action_transformations, not graded_verdicts /
maneuvers, and there is no dual-form parsing to maintain.
Providers¶
builtin.ros2_twist— transformsgeometry_msgs/msg/Twistactuator commands (clamp_velocity,stop_motion,avoid_obstacle). Owns all ROS-specific shape/encoding knowledge.builtin.kubernetes— remediation transforms (cap_replicas). Demonstrates that a non-robotics domain plugs in without touching generic runtime decision code.