Skip to main content

openworldformat (PyPI)

The Open World Format research package. The core — parse a .world manifest, fold its session log — is pure standard library, no dependencies, and deliberately no renderer: this is the format's research surface, not a viewer. Embodied-agent benchmarks (tasks as predicates over the state document, trajectories in the format's own op vocabulary), dataset tooling over session logs (fold a thousand recordings, compute one number), and notebooks — none of that wants three.js or Bevy; all of it wants pip install openworldformat and a fold.

It is also the fold contract's third independently-built implementation, sharing no code or toolchain with the JS reference or the Rust one — every conformance world and outcome assertion the js CI job runs, this package runs too, and the two folds agree byte-for-byte on the example packages.

Install

pip install openworldformat

Use

from pathlib import Path
from openworldformat import read_package, fold_log, to_manifest

# A head-first package: manifest.json is the world now (`head`); the log
# folds over snapshots/base.json back to it.
base, entries, head, package = read_package(Path("world"))

state = fold_log(base, entries)
state["entities"]       # the world at head revision
state["applied_edits"]  # how many edits the log held
to_manifest(state)      # the whole manifest again — the fold is total

The fold applies the spec's rules: only edit ops change the document; tool, input, state and clock fold to nothing; a Batch applies all-or-nothing; ids and names stay unique; deleting an entity deletes its descendants; it stops at the first entry that no longer applies.

Branches are tips: build_history gives a log its shape, fold_path folds any branch of it. Session state ops fold separately, over state.json (fold_state). openworldformat.physics carries the ext-physics extension's executable half — the deterministic reference solver, trajectory write/fold, and the outcome runner:

from openworldformat.physics import simulate_physics, fold_trajectories, run_outcomes

sim = simulate_physics(manifest, {"until_s": 6})  # deterministic
sim["contacts"]   # impacts: {t_s, body, other, position, normal_speed}
sim["resting"]    # where each dynamic body ended up
track = fold_trajectories(entries)  # scrub recorded motion, no solver
run_outcomes(manifest, outcomes_doc)  # the conformance assertions

The solver is deliberately minimal — spheres against floors and axis-aligned statics, fixed 1/120 s semi-implicit Euler, sleep on rest — so the conformance outcome assertions run anywhere and in CI. Reference-grade, not production physics; deterministic within an engine, semantic-only across engines, exactly as the core spec refuses bit-exactness.

Live authoring: agents outside, ops in

What a host does with an agent that wants to change the world: ingest a batch against the fold — names bind to ids (a string where an entity id goes is a name), a spawn without an id gets the next one, partial transforms and materials merge with what's there, keys the format would drop are refused with a path to each, and any failure refuses the whole batch. The state you pass in is never touched:

from openworldformat import fold_log, ingest

done = ingest(state, [{"SpawnEntity": {"entity": {"name": "lamp", "parent": "crate"}}}])
done["ok"]         # True
done["spawned"]    # {"lamp": 3} — the ids the batch's names got
done["ops"]        # the committed ops, bound: serialize into an entry and append
done["state"]      # the new world; the old one is unchanged

merge_patch is the RFC 7396 helper the merges use; manifest_text is the canonical pretty form an authority writes to manifest.json — members sorted, nulls left out, entities by id, plain arrays inline — so the same world is always the same bytes.

Tasks: the benchmark harness

A task is a world, a trajectory, and a goal — a list of predicates over what the fold produces. Scoring is therefore deterministic and needs no engine: fold the log, evaluate the predicates. examples/tasks/ turns the repository's four example packages into a benchmark dataset, each package's own log its solution:

python -m openworldformat.eval examples/tasks/
ok   the-drop-test: the switch scores  (1 edits, 6 ops, 1 authors, revision 1)
ok   forked-exploration: the moat variant wins this branch  (3 edits, 4 ops, 3 authors, revision 4)
ok   hello-world: hang the lantern  (1 edits, 5 ops, 3 authors, revision 1)
ok   speedrun-fork: noor's run, on its own branch  (2 edits, 9 ops, 2 authors, revision 2)

A task file names the world and states the goal; a tip folds a branch (a run, a variant) instead of the head; a budget caps the cost:

{
  "task": "hello-world: hang the lantern",
  "world": "../../../examples/hello-world",
  "budget": { "max_edits": 1, "max_entries": 5 },
  "goal": [
    { "exists": { "entity": "lantern" } },
    { "near": { "entity": "lantern", "position": [-12.0, 0.0, 3.0], "tolerance": 0.5 } },
    { "field": { "name": "score.tour", "equals": 1 } }
  ]
}
Predicate Holds when
{"exists": {"entity": name}} the fold holds an entity by that name
{"gone": {"entity": name}} it doesn't
{"near": {"entity", "position", "tolerance"=0.15}} the entity's folded position is within tolerance
{"field": {"name", "equals"?, "at_least"?, "at_most"?}} the state document's value compares

Budgets (max_edits, max_ops, max_entries, inclusive) are the cost side of a task: solve it, but not by a million edits. Metrics report the trajectory's shape — edits, ops, entries, authors (the audit trail's model-vs-visitor filter is one field), span, revision.

To score an agent, don't write files at all — pass its ops to run_task the moment it emits them:

from openworldformat.eval import run_task

result = run_task(manifest, agent_entries, task, state_doc)
result["ok"], result["failures"], result["metrics"]

This task language is deliberately library-level, not a spec extension; it graduates to spec/extensions/ when a second implementer wants it.

Agents: the benchmark's other half

Scoring a recorded trajectory is one loop; scoring a live agent is the same loop with the recording still wet. run_agent keeps the entries, folds between steps so the agent observes its own edits, and scores with run_task:

from openworldformat.agent import run_agent

result = run_agent(manifest, task, state_doc)  # template_agent inside
result["ok"], result["metrics"], result["entries"]

An agent is f(document, values, task, entries) -> entry | None: the folded world and state values as observation, one entry of ops as action, None to stop. The built-in template_agent is the baseline — a compiler from goal predicates to ops, not a brain; it exists so benchmark authors have a floor to beat and a skeleton to copy. Its entries serialize to ops.jsonl like any recording: an agent run is a log, ready to join a dataset.

Dataset tooling: fold a corpus, compute one number

A folder of .world packages is a dataset — each ops.jsonl a recording, each fold a row:

python -m openworldformat.dataset examples/
world               entities  edits  ops  entries  authors               tips  span_s
forked-exploration  5         4      5    5        host, llm, maya       2     0.4
hello-world         14        1      5    5        llm, maya, visitor-7  1     1.877
speedrun-fork       9         2      15   4        kai, maya, noor       2     20.0
the-drop-test       7         1      6    2        host                  1     0.2

The authors column is the audit trail's dimension — model, host and visitor in one recording, separable by one field. The tips column counts branches; fold each with fold_path and the counterfactuals come with the corpus. summarize(dir) gives the row as a dict for notebooks.

API

Export What it does
parse_manifest(text, strict=False) parse and version-check a world document (strict also enforces the schema's key sets)
parse_log_line(line, strict=False) parse one ops.jsonl line, ops classified
classify_op(op) recognize an op by shape — edits first
op_kind_shape_ok(kind) the shape collision rule: edits PascalCase, history lowercase
edit_ops(entry) an entry's edits, in order
canonical_json(value) the canonical form for hashing — sorted, whitespace-free
compute_entry_id(entry) an entry's content id, sha256:<hex>
manifest_text(manifest) the canonical pretty text an authority writes to manifest.json
fold_log(manifest, entries) the document at the last entry (the linear fold; by-name references bind to ids here, at ingestion)
build_history(entries) a log's ids, parents, children and tips
fold_path(manifest, entries, tip=None) the document at any tip (a branch)
fold_state(state_doc, entries) the state document's values at the last entry
compute_inverse(op, state) the inverse of one edit against the state it's about to change — undo is appending it
merge_branch(state, entries) a branch's entries rewritten onto a main fold, colliding ids reallocated
snapshot_filename(entry_id, revision) where a snapshot goes: by entry id, else by revision
compact_package(package_json, head_revision) the package.json of a compaction
read_package(world_dir) a head-first package: (base, entries, head, package_json)
to_manifest(state) the fold's state as a whole manifest — to_manifest(fold_log(m, [])) is m again
ingest(state, batch) live authoring: bind, validate and apply a batch whole-or-refused; the state passed in is never touched; warnings for what validation warns about in the new world (a behavior whose target the batch deleted)
merge_patch(current, change) JSON merge patch, RFC 7396 — the rule partial transforms merge by
compact(world_dir, head_revision=None) move the base up to the head (or a revision): snapshots/base.json rewritten, the entries it holds archived
ext_provenance(manifest) the provenance extension's five lineage fields, or None

openworldformat.physics mirrors the npm package's openworldformat/physics: collect_physics, simulate_physics, fold_trajectories, trajectory_op, run_outcomes. openworldformat.cinematography mirrors openworldformat/cinematography: camera_of, frame_of, view_of, project, world_origin, aim_point_of, focus_distance_of, shot_list, run_outcomes. openworldformat.soundtrack holds the soundtrack curves — curve_at, beat_at, section_at, modulation_factor — as plain functions over plain numbers, for analysis rather than playback. openworldformat.eval scores tasks (see above): run_task, load_task_file, and the python -m openworldformat.eval CLI. openworldformat.agent runs agents against them: run_agent and the template_agent baseline. openworldformat.dataset summarizes recordings — summarize and the python -m openworldformat.dataset report.

Test

python -m unittest discover -s tests -t .

The suite mirrors the JS tests — it folds the repository's own example packages, replays the drop-test recording through the solver, and runs the conformance outcome assertions — so both references assert the same facts.

Apache-2.0.

Metadata

Release files for openworldformat 0.4.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for openworldformat 0.4.4
File Size Uploaded Provenance
openworldformat-0.4.4.tar.gz 72.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for openworldformat 0.4.4
File Interpreter ABI Platform
openworldformat-0.4.4-py3-none-any.whl Python 3 none any Details

Total release size: 118.6 kB

Release files / openworldformat-0.4.4.tar.gz

Download URL openworldformat-0.4.4.tar.gz
Size 72.0 kB
Tags Source
SHA-256 checksum
How to use checksums
45d91539b5cbcd11885b454363da8c6d22d2207849222e422d7dc0ad65e157b2
BLAKE2b-256 checksum
How to use checksums
1162c96f976a4682269e8db1d5c70b2c6734837cb8c9979959cd87885c1b7aff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / openworldformat-0.4.4-py3-none-any.whl

Download URL openworldformat-0.4.4-py3-none-any.whl
Size 46.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3eaf5e02b4c2054a8bb59c08764edabf0286c181dcbbf5b5492744cd988bfe77
BLAKE2b-256 checksum
How to use checksums
1578b9d7c7365d3725966b3b9683e3f02228b2846f518c3cdf886cf12ca3388c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for openworldformat 0.4.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.4.4 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page