# Tera Arena environments `@lumbridge/tera/arena` is Tera's renderer-independent RL boundary. It imports no Three.js scene, canvas, DOM input, network client, or asset code. The five shipped environments wrap the same fixed-step controllers and plans used by the interactive client: | Environment | Existing simulator | Goal | Safety terminal | |---|---|---|---| | `drive-101-v1` | `VehicleController` + California transport pack | complete a short US-101 or I-5 route leg | guardrail contact | | `office-nav-v1` | `Plan(FRONTIER_VALLEY)` + `createWalker` | reach a collision-clear office waypoint | repeated collision stall | | `office-jobs-v1` | `Plan` + `robotRoutes` + `robotActivity` | complete an authored simulated patrol/delivery/inspection job | collision stall or repeated invalid interaction | | `crow-nav-v1` | `ActorController` in crow flight mode | reach a 3D waypoint | altitude/horizontal envelope contact | | `california-flight-v1` | `AircraftController` | reach a geographic/altitude waypoint | California flight-envelope contact | ## Contract ```ts import { Drive101Environment, driveScriptedBaseline, } from "@lumbridge/tera/arena"; const env = new Drive101Environment(); env.reset(115, { split: "train" }); for (;;) { const result = env.step(driveScriptedBaseline()); if (result.terminated || result.truncated) break; } const checkpoint = env.snapshot(); // JSON-safe and checksummed env.restore(checkpoint); const trace = env.trace(); // actions, component rewards and per-step checksums new Drive101Environment().replay(trace); // throws at the first divergence ``` Every environment implements `tera.arena/v1`: - `reset(seed, scenario)` accepts an exact public scenario id or `{ split: "train" | "dev", id? }`. Omitting `id` selects a scenario from the requested split deterministically from the uint32-normalized seed. - `step(action)` returns an observation, total reward, named reward components, Gym-style `terminated`/`truncated`, and `info`. - `info` pins the semantic environment manifest, materialized scenario, simulator sources, environment sources, seed, step and state checksum. - `snapshot`/`restore` round-trip controller state exactly. Snapshots from another version, scenario, or modified payload are rejected. - `trace` is a canonical, checksummed action/reward/state envelope. `replay` verifies the initial state, every transition, the cumulative reward and final state. The checksum is FNV-1a-64 over canonical UTF-8 JSON; source pins are SHA-256 values checked from the repository by `npm run arena:source-hashes`. Stepping a completed episode is an error. A task outcome sets `terminated`; only the manifest's step cap sets `truncated` with reason `max-steps`. ## Scenarios and evaluation boundary Train and dev ids are public, explicit, and disjoint in each manifest. Seeded jitter is applied only when a scenario is materialized and is included in its hash. This package intentionally contains no “private” split: a private eval published in the client package is not private. Evaluation operators should hold out their scenario definitions and instantiate the same contract in their own package or service. `ARENA_MANIFESTS` is the machine-readable catalogue. Each manifest declares its action and observation fields, component reward meanings, public split ids, fixed step, maximum steps, safety terminals, and baseline claims. ## Reward and baseline policy Rewards are counterweighted rather than progress-only. Progress and sparse success compete with time, control/energy, lane/altitude/heading, collision and safety costs. A policy therefore cannot collect unbounded reward by circling, vibrating controls, leaning on a wall, or remaining still. The tests execute every train and dev scenario at two seeds and require: 1. the documented inaction action to finish below zero without reaching a goal; 2. the exported scripted baseline to terminate at the goal with positive return; 3. scripted return to exceed inaction return; 4. all safety terminal classes to be reachable; 5. seeded reset, snapshot continuation, trace replay and tamper rejection to be exact. These are smoke-proof baselines, not optimal policies. They exist to make reward regressions and impossible tasks fail in CI before any training budget is spent. `office-jobs-v1` observes only current job facts and the current route waypoint; future seeded schedule entries are not leaked. SF and LA definitions are explicit same-floor scenarios tied to resolved room/prop anchors. They are demonstration data and never claim to describe live staff or company operations. ## Adding an environment Keep the environment under `src/arena/`, wrap an existing renderer-neutral controller or plan, expose train/dev scenario ids and a manifest, and add it to `ARENA_MANIFESTS`. Do not import a scene adapter to obtain simulation state. Update `scripts/check-arena-source-hashes.mjs`, pin the new SHA-256 values, and add the same determinism, floor, scripted, safety, snapshot and replay proofs. Run the complete gate: ```bash npm ci npm run arena:source-hashes npm test npm run typecheck npm run build npm run provenance npm run licenses ```