# tera-spatial Arena's bridge to Tera's four renderer-independent spatial environments. The environments themselves live in the `tera` repository, in TypeScript, as `tera.arena/v1`. They are not reimplemented here and they never will be. This package vendors their import closure, runs it in a resident `node` worker, and transports results. The rule the whole thing is built around: > **Never recompute in Python a number that came out of TypeScript.** Rewards, per-step state checksums, scenario materialisation and the four baseline returns that every reward is normalised against are all computed once, inside Tera, and only ever carried across the pipe. ## What is here | Path | What it is | |---|---| | `tera_spatial/worker.mjs` | the resident NDJSON worker: `reset`, `step`, `snapshot`, `restore`, `trace`, `replay`, `oracle`, `checksum` | | `tera_spatial/bridge.py` | `TeraWorker` / `TeraEpisode` — transport, and nothing else | | `tera_spatial/vendor/tera/` | the 23-file, 283 KB import closure of `src/arena/index.ts` | | `tera_spatial/hashes.py` | SHA-256 of all 23, generated; the worker refuses to start if the tree has drifted | | `tera_spatial/closure.py` | the import walk both the sync script and the gate use | | `scripts/sync_tera.py` | reproduces the vendoring from a `tera` checkout | | `tests/test_replay.py` | the replay gate | The tasksets are not here yet. This is the bridge and its correctness proof. ## The gate ```bash uv run python -m unittest discover -s environments/tera_spatial/tests -v ``` 32 episodes — 4 environments x 4 public scenarios x 2 seeds — each driven from Python one JSON step at a time, then replayed in a fresh TypeScript environment. All 32 must reach an identical FNV-1a-64 checksum. Then seven forgeries per environment, each tried twice: raw, where the envelope checksum catches it, and **re-sealed with a checksum Tera itself recomputed**, where only `replay()` re-running the simulator can. All must be rejected. `node` >= 22.18 is required — the vendored sources are raw `.ts` and are type-stripped, not compiled. Set `TERA_NODE` to point at a specific binary. ## Re-vendoring ```bash uv run python scripts/sync_tera.py --tera ~/repos/gitea/tera # copy + regenerate hashes uv run python scripts/sync_tera.py --check # CI: is the tree clean? ``` The closure is walked, not declared, so a new import in `tera` travels with it. A bare specifier is a hard failure: the wheel has no `node_modules` and a simulator that needs one is not a simulator that ships.