Skip to main content

Static verification engine for URML — Universal Robot Language

Project description

URML

A small, opinionated, human-readable language for describing robot intent.

urml.dev


Validator

Status: Phase 1 in flight. Schemas + four-pass validator + urml CLI + JSON Schema export landed at 0.1.0a1 (pre-alpha). Variable-binding type checking and the LLM bridge are the next milestones.

What this is

The static verification engine for URML. Given a URML program, a Layer-1 capability manifest for the target robot, and the active safety envelope, the validator returns one of two outcomes:

  1. Accepted — the program is statically valid; the runtime may execute it.
  2. Rejected with a structured error — the program fails one or more checks; the error is a machine-readable object that a calling tool (often the LLM bridge) can use to revise the program.

The validator is the safety boundary. Per MANIFESTO.md §Design Principles and CLAUDE.md §What Claude Should Never Do:

URML programs are executed only after static verification against the target's capability manifest and active safety envelope. Any "fast path" that skips verification is rejected on review.

Bypassing the validator is structurally hard because the validator and the runtimes are separate processes. A runtime that wanted to skip validation would have to be modified, not merely flagged.

What the validator checks

When fully implemented, the validator runs these checks against every URML program:

Layer-3 (composition) checks

  • The program parses as valid URML against the layer-3 grammar.
  • Every composition operator is well-formed (no empty parallel, no retry with negative bound, no on_error: substitute referencing an undefined behavior).
  • Every $variable reference resolves to a prior store_as.
  • Types match across producer/consumer primitives.

Layer-2 (primitive) checks

  • Every primitive is in the spec (or in a profile the program declares).
  • Every primitive's required arguments are present and well-typed.
  • Profile-specific argument constraints are honored (e.g., drone-profile move_to declares altitude).

Layer-1 (capability) checks

  • The robot's manifest declares every capability the program needs (mobility, manipulation, perception, declared frames, declared locations).
  • Every named location in the program resolves in the manifest or the world model the manifest references.

Safety-envelope checks

  • Every declared limit is honored: max velocity, max payload, max force, max altitude, geofence, force ceilings, no-go zones, link-loss policy.
  • Profile-specific envelope checks (drone people-occupancy, industrial cell perimeter, home people-only zones) are applied for whichever profiles the program declares.

What the validator does NOT do

  • It does not execute the program. That is the runtime's job.
  • It does not parse natural language. That is the LLM bridge's job.
  • It does not generate the URML program. That is an LLM's job, via the LLM bridge.
  • It does not monitor runtime state. Run-time safety (an unexpected obstacle, a sudden wind gust, a person walking into the cell) is the substrate's job. The validator is static; the substrate is dynamic. Both are required for safety.

Language

  • Python, primary implementation. mypy --strict. Public API fully type-annotated.
  • A long-running validator service (e.g., as a sidecar to multiple runtimes in production) may eventually be backed by Rust for deployment ergonomics; the Python implementation remains the reference.

API (sketch)

from urml.validator import validate, ValidationResult

result: ValidationResult = validate(
    program=program_yaml,         # str or parsed dict
    manifest=manifest_yaml,        # str or parsed dict
    envelope=envelope_yaml,        # str or parsed dict
    profiles=("home",),            # which profiles the program declares
    spec_versions={
        "layer-1-hal": "0.1.0",
        "layer-2-primitives": "0.1.0",
        "layer-3-behavior": "0.1.0",
    },
)

if result.accepted:
    runtime.execute(result.program)
else:
    # result.errors is a list of structured errors,
    # designed to be readable by an LLM and used for revision.
    llm_bridge.revise(program_yaml, result.errors)

Core Commitment

The validator is part of the Core Commitment. It will always be Apache 2.0. The safety guarantees of URML flow through this component; gating it behind a license would forfeit them.

Quickstart (current pre-alpha)

cd reference/validator
python -m venv .venv && . .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
pytest

The 22 tests confirm: the red-mug example parses against the schemas; every primitive accepts its minimal valid form; cross-field rules (e.g. move_to requires exactly one of location/pose, capture(media: video) requires duration, release(mode: place) requires at) fire correctly.

What works now at this pre-alpha milestone:

  • Pydantic v2 schemas for Layer-1 (capability manifest), Layer-2 (all 12 RFC-0002 primitives), Layer-3 (composition), the safety envelope, and the top-level URMLProgram.

  • The Step / BehaviorOrStep tagged union accepts the YAML surface ({move_to: {...}}) and the recursive composition forms.

  • The four-pass validatorurml_validator.validate(program, manifest, envelope, profiles) runs argument, capability, envelope, and binding checks and returns a ValidationResult with structured ValidationErrors. Error codes are stable and namespaced (argument.*, capability.*, envelope.*, binding.*); the LLM bridge will consume this format.

  • Example:

    from urml_validator import validate
    
    result = validate(program, manifest, envelope, profiles=("home",))
    if result.accepted:
        runtime.execute(program)
    else:
        for err in result.errors:
            print(err.render())
    

urml CLI

After pip install -e . the urml console script is on PATH:

urml validate examples/home/red-mug.urml.yaml \
  --manifest reference/validator/tests/fixtures/manifests/turtlebot4_home.yaml \
  --envelope reference/validator/tests/fixtures/envelopes/home_default.yaml \
  --profile home

Exit codes: 0 accepted, 1 validation failed, 2 usage error (missing file, bad YAML), 64 internal error.

Add --json to emit the raw ValidationResult for machine consumers (LLM bridge revision flow, CI checks).

JSON Schema export

# Print one schema to stdout (suitable for piping into an LLM prompt fixture).
urml schema --name program

# Write all three schemas to a directory.
urml schema --all --out-dir build/schemas/

Produces Draft 2020-12 schemas for URMLProgram, CapabilityManifest, and SafetyEnvelope. The LLM bridge consumes the program schema as the structured-output contract; robot makers consume the manifest schema when writing manifests by hand.

The Python API mirrors the CLI:

from urml_validator import export_schema, write_schemas

schema = export_schema("program")  # dict
write_schemas(Path("build/schemas/"))  # writes urml-{program,manifest,envelope}.schema.json

What's not in this milestone (lands next):

  • Variable-binding type checking across primitives (e.g., that grasp(target: $foo) requires $foo to be an Object-typed binding, not a Measurement).
  • Geometric geofence containment (polygon-vertex math).
  • The LLM bridge (reference/llm-bridge/).

Related documents

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

urml_validator-0.1.0.tar.gz (106.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

urml_validator-0.1.0-py3-none-any.whl (70.4 kB view details)

Uploaded Python 3

File details

Details for the file urml_validator-0.1.0.tar.gz.

File metadata

  • Download URL: urml_validator-0.1.0.tar.gz
  • Upload date:
  • Size: 106.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for urml_validator-0.1.0.tar.gz
Algorithm Hash digest
SHA256 87fba6ea932be1f79ecee9fe6e0a778b9945951f78376e205ba2445ae67da835
MD5 a1c9470b67a27d38cf62bfebe9ad039f
BLAKE2b-256 e695e01a8e579ed480a018384bb5a52a5d2e967f893052fa16f04d673c5b779a

See more details on using hashes here.

File details

Details for the file urml_validator-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: urml_validator-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 70.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for urml_validator-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 108f6f2089559284f5a94f0d9b812378a495f9606c85b8c81390ca68bb3bad13
MD5 a98c0f2e21731514787aee6949706d55
BLAKE2b-256 99c5eca6180326267e682c81a568b8fdb2e728c877c66ea7558a1d269c37c22f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page