Open World Format

The session log (L1)

ops.jsonl is the one history: one JSON entry per line, each entry a committed batch of ops by one author. It holds what changed the world (edits) and what happened around the change (tool calls, visitor input, state deltas, clocks). The room’s document is the fold of this log over the base — nothing else is authoritative.

The entry

{"revision": 42, "timestamp_ms": 1790000000123,
 "author": {"peer": 3, "name": "maya"},
 "ops": [ … ]}

revision is the document revision after the entry’s edits applied. Only edits bump it; history-only entries carry the current revision, so readers MUST tolerate repeated and non-monotonic-looking revisions between edit entries. Edit entries themselves are totally ordered.

author is who or what did it — a person, a model, a visitor, a host. Authorship is what makes the log an audit trail: “what did the model do here, versus the people?” is a filter on one field.

The op kinds

An entry’s ops hold any mix of five kinds. Each kind is serialized as its own fields (there is no wrapping tag object); an op is recognized by its shape:

{"SpawnEntity": {"entity": {"id": 1, "name": "lighthouse", "transform": …}}}
{"tool": "gen_spawn_primitive", "args": {…},
 "result_hash": "sha256:…", "phase": "blockout", "timestamp_ms": 1790000000131}
{"input": {"actor": "visitor-7", "position": [3.1, 1.8, -2.0],
           "look": [12.0, -4.0], "click": 17}}
{"state": {"score.chest": 10}}
{"clock": {"playing": true, "position_s": 41.5}}
KindWho writes itChanges the document?
edit (an EditOp)the session authority, for anyoneyes — the only kind that does
toolan app, when a tool call runsno — intent, recorded next to the edits it caused
inputan app, sampled (~10 Hz) while recordingno — playthrough replay
statean app, when host state changesno — the game state no document holds
clockan app, on transport eventsno — performances, song worlds, tours

Edits are SpawnEntity, DeleteEntity, ModifyEntity (an entity id plus a field patch), SetEnvironment, SetCamera, SetAmbience, SpawnAudioEmitter, RemoveAudioEmitter, and Batch (all-or-nothing). Deleting an entity deletes its descendants. Every edit has a computable inverse; undo is appending the inverse — the log never rewinds.

Compatibility

New op kinds MUST fold to nothing for readers that don’t know them, and readers MUST keep reading logs written before a kind existed. The reference rule: op kinds are recognized by shape, edits first — so a log containing only edits (every log written before this format had history kinds) parses unchanged, and an edit serializes today exactly as it always did.

Snapshots

A snapshot is the folded document written to snapshots/rev-<N>.json: derived, never authoritative, deletable without loss — the fold from the base reaches the same state. Compaction (folding to a new base and keeping the old log for history) changes nothing observable.

Replay and determinism

Three levels, and only the first two are part of this format:

  1. Structural replay — fold to any revision. Exact by construction: the fold is the document’s history. Anything that folds to the same state — on any machine, in any language — is conformant here.
  2. Semantic replay — re-run triggers and behaviors offline over the log’s input and state entries. The contract: the same fold plus the same inputs produce the same trigger outcomes and the same state trajectory. Frames are approximately the same — input is sampled (~10 Hz), behaviors are functions of folded time, and renderers draw.
  3. Bit-exact replay — the same pixels. Not part of this format, and MUST NOT be promised by implementations of it. Floats, physics ordering and renderer differences make it a lie waiting to be caught; package.json’s seed is reserved for engines that want to try anyway, and means nothing to the contract above.