Repository navigation
Conversation
…per step) envs/spatial_gym_env serves Spatial-Gym (https://github.com/lkaesberg/Spatial-Gym): one episode is one SPaRC grid puzzle, solved one move per step with the prompts and move parser of the Spatial-Gym paper (arXiv 2604.09338). The reward is 1.0 when the line matches a stored solution, else 0.0. reset() takes puzzle_id, difficulty, seed, split (test/train), backtracking and max_steps. The move parser is in models.py so clients can use it (SpatialGymAction.from_reply); the prompts are server-only. Also adds tests/envs/test_spatial_gym_environment.py (skipped without Spatial-Gym), the docs page stub, card and toctree entry, and discovery.json.
- The move parser moved into models.py (clients use it), the paper's prompts into server/prompts.py (server-only), as OpenEnv's "shared code goes in models.py" invariant asks. - server/app.py: main() parses its own --host and --port, which OpenEnv's tests/envs/test_server_main_args.py requires. The code now matches envs/spatial_gym_env in openenv/OpenEnv#1430 apart from names and documentation links. 9 tests pass, and openenv validate passes statically and against a running server.
|
Very cool. Do you have any visual to understand these environments? |
render_web() draws the SPaRC board with the line so far (server/board_svg.py, in the colours of the SPaRC figures), and web_actions() offers one button per legal move. The observation gains `path`, the line so far. README: a playground screenshot under the first paragraph and an animation of a level-5 puzzle solved move by move.
|
Thanks! Yes, here is one episode: a level-5 puzzle solved one move per step. The line starts at the big circle and has to reach the exit at the bottom left while following every rule on the board (stones of different colours apart, stars in pairs, the triangle's edge count, the polyomino's shape, the dot). I also added Both images are in the README now. They are hosted in the Spatial-Gym repo; happy to move them to |
|
Hi @burtenshaw, just a small friendly reminder about the Spatial-Gym environment, whenever you find the time. If there's anything you'd like changed, I'm happy to update it. Thanks! |
The prompts said a negative polyshape cancels a positive one of the exact same shape, and the backtracking prompt allowed rotating polyshapes. The puzzles use area subtraction and no rotation. The prompts now match SPaRC 0.7.0.
Pass state_cls to create_app, as the new test_env_state_cls_wiring check requires. Without it the HTTP /state body only had episode_id and step_count.
The repository moved to the openenv organization (openenv#1518). Update the pip install commands and the documentation_url accordingly. The Docker base image stays as is until the openenv images are public.
|
Hi @burtenshaw @sergiopaniego, thanks for the docs fix! I also updated the links to openenv/OpenEnv after the move. Happy to change anything else if needed! |


Summary
Adds
envs/spatial_gym_env, which serves Spatial-Gym (paper). One episode is one SPaRC grid puzzle: the agent draws a line from the start node to the exit, one move per step, and the line has to follow every rule on the board. The reward is 1.0 when the line matches one of the puzzle's stored solutions, else 0.0. In the paper, humans solve 98.0% of the test puzzles and the best model, GPT-OSS 120B, 16.0%.Type of Change
Alignment Checklist
.claude/docs/PRINCIPLES.mdand this PR aligns with our principles.claude/docs/INVARIANTS.mdand no invariants are violated.claude/hooks/lint.shon the new files and the testsRFC Status
Test Plan
PYTHONPATH=src:envs uv run --with "Spatial-Gym>=0.1.5" pytest tests/envs/test_spatial_gym_environment.py -v: 9 passed. The tests replay a stored solution for one puzzle per difficulty level (reward 1.0), check that a wrong line scores 0.0, that backtracking undoes a move, the reset options, that sessions are independent, and play a full puzzle throughSpatialGymEnvover WebSocket. Without Spatial-Gym installed the file is skipped, as in CI.tests/envs/test_manifest_app_targets.py,test_server_main_args.py,test_discovery.py,test_hub_canonical_dockerfiles.py,tests/discovery(334 passed), andpython scripts/sync_env_docs.py --check.openenv validate --level static --skip-buildpasses.openenv build(in-repo mode) builds the image; the container solves a level-4 puzzle in 35 moves for reward 1.0, serves the web UI with the README, and passesopenenv validate --url.usort checkandruff format --checkpass on the new files.server/prompts.pykeeps the paper's prompt text byte for byte, so it carries a# ruff: noqa: W291, W293for the trailing spaces inside the strings.Notes for review:
reset()options:puzzle_id,difficulty(a level 1–5 or a list),seed,split(testortrain),backtracking,max_steps(default 100, as in the paper). Unknown options raise, because the server would otherwise drop them quietly.metadata.SpatialGymAction.from_reply(text)reads a move with the paper's parser, which lives inmodels.pyso clients can use it.huggingface/documentation-images, like the other envs.openenvorg. Hugging Face now needs a PRO plan for Docker Spaces on a personal account.Claude Code Review
Prepared with Claude Code. Manual check against
.claude/docs/INVARIANTS.md: the client imports onlymodels.py, the server never imports the client, the reward is computed inside the environment, and the agent-facing surface is the observation text only. No MCP tools exposereset(),step()orstate(). Pydantic models are used throughout, andreset/stepfollow the base signatures. Sessions share no mutable state: each episode deep-copies a read-only template of the Spatial-Gym env.Note
Low Risk
Additive example environment with isolated server code; main operational note is runtime dependency on Hugging Face dataset downloads and the external Spatial-Gym package, not changes to core OpenEnv infrastructure.
Overview
Introduces
envs/spatial_gym_env, a new OpenEnv environment that wraps Spatial-Gym for step-by-step SPaRC grid pathfinding. Each episode is one puzzle: agents move one direction per step (SpatialGymAction), get the paper’ssystem_promptand per-stepprompt, and receive 1.0 only when the path matches a stored solution.The server integrates the underlying
Spatial-Gymgymnasium env via deep-copied templates per session, loadslkaesberg/SPaRCon first reset per split, exposes HTTP/WebSocket throughcreate_app, and adds a/webplayground (SVG board + legal-move buttons). The client includesSpatialGymAction.from_replyfor paper-styleFinal:parsing.Documentation is wired in (
spatial_gym.md, environments index card, toctree) along withdiscovery.json, Docker packaging, andtests/envs/test_spatial_gym_environment.py(gold solutions, WebSocket E2E, skipped withoutSpatial-Gyminstalled).Reviewed by Cursor Bugbot for commit b2e3e47. Bugbot is set up for automated code reviews on this repo. Configure here.