Skip to content

Explicit Safety Abstractions

OMSH safety semantics are defined by environment models, not by logging wrappers. This follows the useful part of the abstraction architecture in ~/Projects/quartz/com and ~/Projects/topaz/rl-skeleton while preserving OMSH's probabilistic joint-graph pipeline.

Contract

src.environments.safety.SafetyAbstraction is the structural protocol:

  • agent_ids declares the exact environment order and scope;
  • abstract_state(observation) projects the public observation onto the state needed for safety labelling; and
  • is_safe(state, agent_id) labels that projection for an explicit focal agent.

The current objectives are binary and per-agent, so every production model returns the immutable AgentSafetyState. Its unsafe_agents set is the safety-only quotient of the public Markov state. It deliberately excludes reward, time, and transition metadata.

The concrete model inventory is:

Family Model Safety projection
Gridworld CongestionSafetyModel vehicles involved in adjacent same-slot merge collisions
Matrix BertrandSafetyModel global price-war flag
Matrix ChickenSafetyModel global crash flag
Matrix InspectionSafetyModel global undetected-violation flag
Matrix DPGGSafetyModel agents exploited by a withholding teammate
Gridworld GatheringSafetyModel agents missing from active channels
Gridworld IceDuelSafetyModel agents occupying edge cells
Gridworld MarkovStagHuntSafetyModel damaged agents
Gridworld PursuitSafetyModel global all-intruders-on-goals failure

Each labelled wrapper constructs its model from static environment structure and passes it to LabelledEnv. LabelledEnv.safe(...) delegates projection and labelling to that required model.

Runtime and graph consistency

The same model now serves both consumers:

  1. LabelledEnv.step(...) labels the tracked agent's returned observation and records cost/cumulative_cost.
  2. unsafe_keys_from_abstraction(...) labels learned or exact graph nodes before sound value iteration.

This removes a duplicated semantic path and makes the focal agent explicit. Previously unsafe_keys_from_env(...) called safe(flat) without forwarding the shield bundle's agent_id, so a bundle requested for player_1 was still labelled with the default player_0 objective. Bundle construction now passes agent_id through for learned and true-policy shields. The labelled wrapper also passes self.agent_id when accounting runtime cost.

SHIELD_SEMANTICS_VERSION is explicit_safety_abstraction_v3; old cached transition-shield bundles must be rebuilt. The version bump is important even where player_0 labels happen to be unchanged, because a cached non-default-focal bundle may contain the old labels.

Relationship to the reference repositories

The reference repositories also define exact transition outcomes, temporal logic label alphabets, safety projections, and centralized benchmark registries. Those layers are not copied into OMSH:

  • exact and learned transition outcomes already live in joint-graph Edge values (env_prob, joint action, successor, and rewards);
  • probabilistic shielding consumes those graphs directly rather than building an LTL product over a second transition model; and
  • OMSH experiments intentionally use notebook-specific configurations and agent counts, so one fixed default-environment registry would not be a production source of truth.

If OMSH later adds temporal objectives, extend the model contract with an explicit label alphabet and monitor state. If it adds a second transition representation, first establish why graph edges cannot remain the sole source of transition semantics; parallel exact kernels create a high risk of drift.

Adding an environment

For a new labelled environment:

  1. Define a named safety model beside its labelled wrapper.
  2. Copy only static shape/agent metadata from the environment; do not retain mutable episode state in the model.
  3. Return an immutable projection from abstract_state(...).
  4. Validate observation shape and unknown agent IDs loudly.
  5. Pass the model to LabelledEnv and export the model from the environment package.
  6. Add tests for safe and unsafe projections, every agent whose labels differ, runtime cost accounting, and graph-node labelling.

Safety projection tests live in tests/test_environment_contracts.py; focal-agent graph labelling is covered in tests/test_shield.py.