Level 1 · self-serve

Plug your robot

One command puts the gate in front of a body. You start in monitor — it watches and explains, but changes nothing — and flip to enforce only when you trust it. Adding a robot is one YAML profile, never new code.

quickstart · bumi
# 1. pull the gate for your transport — public image, nothing to build
docker pull thinkneoai/bridge:dds

# 2. observe first — monitor never blocks, just shows verdicts
docker run --rm --network host thinkneoai/bridge:dds \
    --profile bumi --mode monitor

# no robot handy? the base image governs a replay with no bus:
#   docker run --rm thinkneoai/bridge --profile bumi --mode enforce \
#       --replay samples/bumi.jsonl --out log

Start: --mode monitor

Every proposed command is forwarded verbatim and the verdict is logged advisory-only. Your robot behaves exactly as before — you just gain a full audit of what governance would do.

Flip: --mode enforce

The gate becomes the sole writer of the body's command topic. Denied commands never reach the body; out-of-envelope values are clamped to the safe limit and audited. Confidence first, enforcement second.

Profile registry

A profile is data, not code. These four ship today — three proven on a real wire, one annotated template to fork. All validate against docs/profile.schema.json.

bumi
DDS (CycloneDDS) · native CDR struct, byte-native
proven on wire
lumos
LCM · robot_cmd_lcmt, byte-exact
proven on wire
turtle_ros2
ROS 2 · geometry_msgs/Twist
proven on wire
EXAMPLE.annotated
any · copy this to start your own
template

My robot isn't on the list

Good — that's the common case, and it never needs us. You describe your body in one YAML file and the same gate governs it. We don't claim to "already support" bodies we haven't proven; you bring or write the profile.

  1. 1Copy the template. Start from profiles/EXAMPLE.annotated.yaml — every field is documented inline.
  2. 2Describe the wire. Give your native struct fields (or the message type) so the gate can re-encode to the exact bytes your controller expects.
  3. 3Map both directions. in_map: native → canonical; out_map: canonical → native. The gate only ever speaks canonical; your vendor verbs die in the maps.
  4. 4Set hardware limits. Per-action clamps that may only tighten the safety envelope — never widen it.
  5. 5Validate, then monitor. python -m rgov.profile.validate my_profile.yaml, then run --mode monitor before you ever enforce.
profiles/EXAMPLE.annotated.yaml (excerpt)
profile: example-bot
vendor: ExampleRobotics
capabilities: [locomotion, posture, safety]

transport:                      # adapter chosen from `type` — never a Python class
  input:  {type: dds, topic: example/cmd/proposed}
  output: {type: dds, topic: example/cmd}   # the gate is the SOLE writer here

in_map:                         # native event -> canonical command
  discriminator: "$verb"
  cases:
    "0": {action: MOVE, params: {linear.x: "$velocity[0]", angular.z: "$velocity[1]"}}
    "21": {action: POSE, params: {name: "lie"}}
  on_unmapped: DENY             # everything else is fail-closed

out_map:                        # canonical -> native (gate re-encodes to YOUR struct)
  MOVE: {fields: {verb: 0, velocity: ["$linear.x", "$angular.z"], arg: 0}}

limits:                         # hardware clamps — may only TIGHTEN the envelope
  MOVE: {linear.x: [-0.5, 0.5], angular.z: [-0.5, 0.5]}

governance:                     # a default policy you ship; operators can override
  default: APPROVE
  rules:
    - {id: deny_fast_move, action: MOVE, field: linear.x, op: abs_gt, value: 1.0,
       decision: DENY, reason: "commanded speed above safe limit"}