-
Notifications
You must be signed in to change notification settings - Fork 141
Comparing changes
Open a pull request
base repository: sail-sg/envpool
base: v0.9.0
head repository: sail-sg/envpool
compare: v0.9.1
- 12 commits
- 69 files changed
- 1 contributor
Commits on Mar 23, 2026
-
[envpool] migrate XLA custom calls to OpenXLA FFI (#343)
## Summary - Problem: EnvPool's JAX custom call path still relied on the legacy untyped API on GPU, and the new FFI headers were wired through Python-version-specific `jaxlib` wheel repos. - Scope: Switch EnvPool custom calls to typed OpenXLA FFI and pin the exported FFI headers from the GitHub `openxla/xla` source snapshot that `jax-v0.9.2` already references. - Outcome: GPU custom calls no longer go through the legacy API path, and Bazel no longer depends on dynamically extracted `pip_requirements_*_jaxlib` headers for C++ compilation. This updates the XLA integration to match current JAX FFI expectations while keeping the header dependency sourced from upstream GitHub code. ## Technical Details - Approach: Replace the legacy custom call ABI with typed FFI handlers in C++, pass the handle as an FFI attr from Python, and fetch only the `xla/ffi/api` subtree from the XLA source commit pinned by `jax-v0.9.2`. - Code pointers: - `envpool/core/xla_template.h`: rewrites the custom call bridge to use `xla::ffi` typed handlers for CPU and GPU. - `envpool/python/xla_template.py`: registers API version 1 FFI targets and threads the custom handle through attrs with input/output aliasing. - `envpool/workspace0.bzl`: adds the pinned `openxla_ffi_headers` source archive. - `third_party/openxla_ffi/ffi_api.BUILD`: exposes only the exported FFI headers with the expected include prefix. - Notes: the external FFI headers come from `openxla/xla@187a5eb58277a85847d1516bd1e20b7faf03d5ef`, which is the XLA revision referenced by `jax-v0.9.2`. ## Test Plan ### Automated - `brix ssh dev-0 -C -- 'cd /root/code/envpool && USE_BAZEL_VERSION=8.6.0 bazel --output_user_root=/tmp/envpool-openxla-source-subtree-bazel build //envpool/core:py_envpool --@rules_python//python/config_settings:python_version=3.11'`: passed - `brix ssh dev-0 -C -- 'cd /root/code/envpool && USE_BAZEL_VERSION=8.6.0 bazel --output_user_root=/tmp/envpool-openxla-source-subtree-bazel build //envpool/core:py_envpool --@rules_python//python/config_settings:python_version=3.12'`: passed - `brix ssh dev-0 -C -- 'cd /root/code/envpool && USE_BAZEL_VERSION=8.6.0 bazel --output_user_root=/tmp/envpool-openxla-source-subtree-bazel build //envpool/core:py_envpool --@rules_python//python/config_settings:python_version=3.13'`: passed - `brix ssh dev-0 -C -- 'cd /root/code/envpool && BAZELOPT="--output_user_root=/tmp/envpool-openxla-subtree-wheel-bazel2" make bazel-build'`: passed - `brix ssh dev-0 -C -- 'cd /root/code/envpool && /tmp/envpool-issue303-fix-venv/bin/python examples/xla_step.py'`: passed earlier during the typed FFI migration validation on `dev-0` ### Suggested Manual - `pip install <built wheel> "jax[cuda12]" gym packaging`: verify install against the same JAX family used in the repro. - `python examples/xla_step.py`: confirm the GPU path runs without the old `API_VERSION_ORIGINAL` warning.
Configuration menu - View commit details
-
Copy full SHA for a8c4620 - Browse repository at this point
Copy the full SHA a8c4620View commit details -
[envpool] Fix explicit episodic-life reset for Atari and Vizdoom (#344)
## Summary - Problem: explicit `env.reset()` did not fully reset underlying state for episodic-life envs, so repeated resets could continue the same game/session instead of starting a fresh episode. - Scope: preserve the existing `force_reset` signal through the core async env path, make Atari and Vizdoom honor explicit resets under `episodic_life`, add regression coverage for both Python-facing APIs, and keep the branch green against current lint drift. - Outcome: explicit user resets now route to a real underlying reset for both env families instead of being treated like episodic-life continuation. Fixes #301 by restoring explicit reset semantics for episodic-life envs. ## Technical Details - Approach: thread the existing `force_reset` bit from `AsyncEnvPool` into `Env::PreProcess`, then consume it in env-specific reset logic. - Code pointers: - `envpool/core/env.h`: stores `force_reset_` on the env instance and threads it through `EnvStep`/`PreProcess`. - `envpool/core/async_envpool.h`: forwards `raw_action.force_reset` instead of collapsing explicit resets into generic reset handling. - `envpool/atari/atari_env.h`: treats explicit resets as a full `reset_game()` even when `episodic_life=True`. - `envpool/vizdoom/vizdoom_env.h`: treats explicit resets as a full `newEpisode()` even when `episodic_life=True`. - `envpool/atari/atari_env_test.cc`: adds a C++ regression test for repeated explicit resets. - `envpool/atari/atari_envpool_test.py`: adds a gymnasium regression test matching the user-facing Atari repro. - `envpool/vizdoom/vizdoom_test.py`: adds a Python regression test for repeated explicit resets under Vizdoom episodic life. - `envpool/core/xla_template.h`: fixes current `clang-tidy` / lint complaints encountered while validating this branch. - Notes: the Linux `make bazel-test` run on `dev` used `--distdir` with a locally downloaded `pretrain.tar.gz` and an Atari ROM override to avoid unrelated external download failures during validation. ## Test Plan ### Automated - `make bazel-test BAZELOPT="--distdir=/tmp/bazel-distdir-test --override_repository=atari_roms=/tmp/atari_roms_override_test"` on `dev`: passed (`30 / 30 tests pass`) before the Vizdoom follow-up. - issue #301 Atari repro script on `dev` against a patched wheel: passed (`info["lives"]` stayed at 5 across repeated `reset()`). - `ruff check envpool/vizdoom/vizdoom_test.py`: passed. - `ruff format --check envpool/vizdoom/vizdoom_test.py`: passed. - `clang-format --style=file -n --Werror envpool/vizdoom/vizdoom_env.h` on `dev`: passed. ### Known Verification Gap - Targeted `//envpool/vizdoom:vizdoom_test` execution on `dev` currently crashes in existing test setup with `v_video.cpp:1346 Assertion 'CleanWidth >= 320' failed`, including the pre-existing `test_timelimit` case. That prevented runtime confirmation of the new Vizdoom regression test on this box, but the failure reproduces independently of this patch.
Configuration menu - View commit details
-
Copy full SHA for 623637f - Browse repository at this point
Copy the full SHA 623637fView commit details -
[envpool] auto-register minigrid environments (#345)
## Summary - Problem: the top-level `envpool` import path never loaded `envpool.minigrid.registration`, so MiniGrid envs were documented and individually registered but absent from `envpool.list_all_envs()` and failed in `envpool.make(...)`. - Scope: wire MiniGrid into the top-level registration and build targets, and add a focused regression test for the normal make path. - Outcome: MiniGrid envs are available from a standard `import envpool` again, and `make_gymnasium("MiniGrid-Empty-5x5-v0")` succeeds. This fixes #311. ## Technical Details - Approach: import `envpool.minigrid.registration` from `envpool.entry`, then mirror that dependency in Bazel so the top-level `envpool` target keeps the registration module and extension available. - Code pointers: - `envpool/entry.py`: adds MiniGrid to automatic registration on `import envpool` - `envpool/BUILD`: adds MiniGrid registration/runtime deps to the top-level target - `envpool/make_test.py`: adds targeted regression coverage for MiniGrid creation - Notes: keeps the existing generic `test_list_all_envs` unchanged and puts the MiniGrid assertion in its own test. ## Test Plan ### Automated - `brix ssh dev-0 -C -- 'chmod +x /tmp/envpool_issue311_fix_verify.sh && bash /tmp/envpool_issue311_fix_verify.sh /tmp/envpool_issue311_fix_repo.tar.gz'`: passed; `//envpool:make_test` ran `_MakeTest.test_list_all_envs` and `_MakeTest.test_make_minigrid` successfully on Linux/Python 3.12 ### Suggested Manual - `python -c 'import envpool; print("MiniGrid-Empty-5x5-v0" in envpool.list_all_envs())'`: verify the task is registered from the top-level import path - `python -c 'import envpool; envpool.make("MiniGrid-Empty-5x5-v0", env_type="gymnasium", num_envs=2)'`: verify the original issue reproducer now succeedsConfiguration menu - View commit details
-
Copy full SHA for db063c0 - Browse repository at this point
Copy the full SHA db063c0View commit details -
[envpool] sync .bazelversion to Bazel 8.6.0 (#346)
## Summary - Problem: `.bazelversion` still pins Bazel `6.0.0` even though the repo's Makefile, Dockerfiles, docs, and modernization plan already moved the Bazel toolchain to `8.6.0`. - Scope: update only `.bazelversion` to `8.6.0`; no other toolchain or test changes are included here. - Outcome: Bazelisk and the rest of the repo's Bazel configuration point at the same version again, avoiding version-selection drift. This keeps the fix surface to a single file while restoring consistency across the repo's Bazel entrypoints. ## Technical Details - Approach: sync the checked-in Bazelisk version file with the existing Bazel 8 configuration that is already referenced elsewhere in the repo. - Code pointers: - `.bazelversion`: update the Bazelisk-resolved version from `6.0.0` to `8.6.0`. - Notes: this is intentionally split out from the multiplayer regression fix so the tooling repair can land independently. ## Test Plan ### Automated - `python3 - <<'PY' ...`: verified `.bazelversion`, `Makefile`, `docker/dev.dockerfile`, and `docker/release.dockerfile` all point to `8.6.0`. ### Suggested Manual - `bazelisk version`: confirm the repo now resolves Bazel `8.6.0`. - `make bazel-test`: confirm the standard Bazel entrypoint no longer fights the stale `.bazelversion` pin.
Configuration menu - View commit details
-
Copy full SHA for ffd7508 - Browse repository at this point
Copy the full SHA ffd7508View commit details -
[envpool] fix multiplayer players.env_id inference (#347)
## Summary - Problem: the simplified Python multiplayer action path was filling `players.env_id` with the batch `env_id`, so flattened per-player actions were grouped against the wrong environments when an env contributed more than one player action. - Scope: infer `players.env_id` from the incoming Python action payload, reuse the latest observed player-to-env mapping when player counts vary by env, and add Python-side regression coverage for the multiplayer wrapper path. - Outcome: multiplayer actions sent through the shorthand Python API now preserve the correct per-player env mapping instead of silently slicing the action buffer incorrectly. This fixes the Python wrapper bug behind issue #296 without changing the C++ action parser contract. ## Technical Details - Approach: teach `EnvPoolMixin._from()` to derive `players.env_id` from player-shaped action arrays, fall back to the cached `info:players.env_id` mapping from the last `recv()`, and raise when the mapping is ambiguous instead of fabricating a wrong one. - Code pointers: - `envpool/python/envpool.py`: adds `players.env_id` inference and caches `info:players.env_id` on `recv()` for variable-player batches. - `envpool/dummy/dummy_py_envpool_test.py`: adds regression coverage around the real dummy DM wrapper for uniform multiplayer, cached variable-player, explicit mapping, and ambiguous-input cases. - `envpool/dummy/BUILD`: wires the dummy Python test to the Python API wrapper target. - Notes: the regression test now uses the existing dummy env wrapper rather than a standalone fake mixin harness. ## Test Plan ### Automated - `python3 -m py_compile envpool/python/envpool.py envpool/dummy/dummy_py_envpool_test.py`: passed. ### Suggested Manual - `USE_BAZEL_VERSION=8.6.0 bazelisk test //envpool/dummy:dummy_py_envpool_test --config=test --spawn_strategy=local --test_output=errors`: exercise the real dummy wrapper path on Linux. - Re-run the issue #296 repro against this branch on `dev-0`: confirm the flattened multiplayer action now expands to the expected `players.env_id` sequence instead of the old one-element-per-env mapping.
Configuration menu - View commit details
-
Copy full SHA for c5c56fe - Browse repository at this point
Copy the full SHA c5c56feView commit details -
[examples] reset CleanRL Atari stats on truncation (#348)
## Summary - Problem: `RecordEpisodeStatistics` in the CleanRL Atari example carries episode return/length across time-limit truncation when `episodic_life=True`. - Scope: Update the example wrapper so Atari stats reset on true episode boundaries (`terminated` or `truncated`) instead of only when lives reach zero. - Outcome: Episode return and length no longer leak into the next timeout-delimited episode in the issue #299 repro. This keeps the fix scoped to the example wrapper and aligns its bookkeeping with EnvPool's episode semantics under Atari time limits. ## Technical Details - Approach: Reuse the existing `terminated` / `truncated` signals from the wrapped env and reset tracked stats on either condition in the `has_lives` path. - Code pointers: - `examples/cleanrl_examples/ppo_atari_envpool.py`: derive `term` / `trunc` in both gym API branches and use them to clear `episode_returns` / `episode_lengths`. - Notes: This intentionally does not change core EnvPool Atari runtime behavior; it only fixes the example-side statistics wrapper. ## Test Plan ### Automated - `python3 -m py_compile examples/cleanrl_examples/ppo_atari_envpool.py`: passes - `dev: source /tmp/envpool-issue299/venv/bin/activate && python /tmp/envpool_issue299_repro.py`: before fix the repro reported `episode=1 expected_return=10.0 recorded_return=20.0 expected_len=31 recorded_len=60`; after the fix it reports `episode=1 expected_return=10.0 recorded_return=10.0 expected_len=31 recorded_len=31` ### Suggested Manual - `python3 examples/cleanrl_examples/ppo_atari_envpool.py ...`: run the Atari example with a short `max_episode_steps` setup and verify `info["r"]` / `info["l"]` reset after timeout boundaries
Configuration menu - View commit details
-
Copy full SHA for 30e49a9 - Browse repository at this point
Copy the full SHA 30e49a9View commit details -
[envpool] support per-env seed sequences (#349)
## Summary - Problem: EnvPool only accepted scalar seeds and derived each env seed as `seed + env_id`, so callers could not assign explicit per-env seeds. The recent `players.env_id` inference logic also broke the single-player XLA send path by materializing traced `env_id` values through NumPy. - Scope: Accept `seed` as an int or per-env sequence at the Python API, thread per-env seeds through core env creation and VizDoom, add dummy regression coverage, and preserve traced single-player `env_id` arrays in the Python action path. This does not change multiplayer inference rules or add extra `make_test` coverage. - Outcome: `envpool.make(..., seed=[...])` now assigns one seed per env, VizDoom consumes the resolved per-env seed, and the Atari XLA API test passes again on dev. This diff adds per-env seed sequences end-to-end and keeps the single-player XLA send path working. ## Technical Details - Approach: Normalize sequence seeds in registration into an `env_seed` config vector, resolve each env instance seed from that vector when present, and defer NumPy conversion of `env_id` until multiplayer-only inference actually needs a NumPy array. - Code pointers: - `envpool/registration.py`: validates `seed` and `env_seed` sequences, length, and int32 bounds before generating config. - `envpool/core/env.h`: resolves each env seed from `env_seed` instead of always using `seed + env_id`. - `envpool/python/envpool.py`: preserves traced single-player `env_id` arrays so JAX/XLA send paths avoid `TracerArrayConversionError`. - `envpool/dummy/dummy_py_envpool_test.py`: covers per-env seed override behavior in the dummy Python envpool path. - Notes: `envpool/python/gym_envpool.py` now matches the existing gymnasium wrapper's mypy ignore so `make lint` no longer fails on the metaclass annotation. ## Test Plan ### Automated - `python3 -m py_compile envpool/python/envpool.py`: passed - `python3 -m py_compile envpool/python/gym_envpool.py`: passed - `python3 -m mypy envpool/python/envpool.py`: passed - `python3 -m mypy envpool/python/gym_envpool.py`: passed - `python3 -m ruff check envpool/python/envpool.py`: passed - `python3 -m ruff check envpool/python/gym_envpool.py`: passed - `python3 -m ruff format --check envpool/python/envpool.py`: passed - `python3 -m ruff format --check envpool/python/gym_envpool.py`: passed - `bazel test //envpool/atari:atari_envpool_test --config=test --test_output=all --test_filter=_AtariEnvPoolTest.test_xla_api` on `dev`: passed - `make bazel-test` on `dev`: passed ### Suggested Manual - `python -c "import envpool; env = envpool.make_gym('Catch-v0', num_envs=3, seed=[3, 5, 7]); print(env.config['env_seed'])"`: verify explicit per-env seed sequences are accepted and preserved. - `bazel test //envpool/atari:atari_envpool_test --config=test --test_filter=_AtariEnvPoolTest.test_xla_api`: recheck the focused XLA regression if you want the narrowest replay.Configuration menu - View commit details
-
Copy full SHA for 996e97d - Browse repository at this point
Copy the full SHA 996e97dView commit details
Commits on Mar 24, 2026
-
[vizdoom] expose combined dm action as discrete (#350)
## Summary - add explicit discrete metadata to C++ specs and plumb it into Python array specs - use that metadata only for Vizdoom combined actions so dm_env exposes a discrete action spec even though the transport dtype is float - add a regression test for `make_spec("D1Basic-v1", use_combined_action=True).action_spec()` ## Testing - python3 -m py_compile envpool/python/data.py envpool/python/protocol.py envpool/vizdoom/vizdoom_test.py - devbox validation in progress: `make lint`, targeted Bazel tests, then `make bazel-test`Configuration menu - View commit details
-
Copy full SHA for 26b2e4e - Browse repository at this point
Copy the full SHA 26b2e4eView commit details -
[mujoco] support xml_file overrides across gym envs (#351)
## Why The original report in #295 was against `envpool==0.8.4` / `Ant-v4`, but the same root cause still exists on current `main` for supported Mujoco Gym tasks when `xml_file=...` is passed through registration. ## Summary - add `xml_file` to the remaining Mujoco Gym env configs that still rejected the kwarg - route those env constructors through `spec.config["xml_file"]` instead of hardcoded asset names - keep the regression coverage narrow by extending the existing deterministic test with a `HalfCheetah-v5` smoke check ## Test plan - `make bazel-test` on `dev` (`Executed 30 out of 30 tests: 30 tests pass.`) - `make lint` on `dev` (current run has `ruff`, `ruff format --check`, `mypy`, `cpplint`, `clang-format`, `docstyle`, and `spelling` clean; `clang-tidy` long-tail build is still running)
Configuration menu - View commit details
-
Copy full SHA for 81347a0 - Browse repository at this point
Copy the full SHA 81347a0View commit details -
[mujoco] build MuJoCo from source on Linux (#352)
## Summary - Problem: current main still consumes the MuJoCo 3.6.0 Linux binary tarball, while the old source-build PR #141 is stale and conflicting. - Scope: switch MuJoCo to the 3.6.0 source archive, add Bazel BUILD wiring for MuJoCo's upstream third-party dependencies, and link EnvPool against the source-built library. This does not change MuJoCo test tolerances or broaden the runtime surface beyond the existing Linux path. - Outcome: current main can build MuJoCo from source on Linux, and this PR supersedes the old #141 attempt on top of the current tree. This redoes the old MuJoCo source-build work against today's main branch and MuJoCo 3.6.0 layout. ## Technical Details - Approach: replace the prebuilt MuJoCo archive with the upstream 3.6.0 source tarball, add minimal BUILD files for tinyxml2, lodepng, tinyobjloader, MarchingCubeCpp, libccd, and qhull, and compile `@mujoco//:mujoco_lib` directly from source with static deps. - Code pointers: - `envpool/workspace0.bzl`: fetch MuJoCo 3.6.0 source plus its upstream third-party archives. - `third_party/mujoco/mujoco.BUILD`: compile MuJoCo from source, including the C++20 toolchain requirement for 3.6.0. - `envpool/mujoco/BUILD`: stop packaging the prebuilt `libmujoco.so` now that EnvPool links the source-built library directly. - `third_party/marchingcubecpp/marchingcubecpp.BUILD`: generate the implementation translation unit required for the marching-cubes symbols MuJoCo uses. - Notes: the Linux validation exposed two current-main deltas from the 2022 PR shape: MuJoCo 3.6.0 now requires C++20, and MarchingCubeCpp needs an explicit implementation TU instead of header-only wiring. ## Test Plan ### Automated - `brix ssh dev -C -- 'bash /tmp/envpool_mujoco_source_dev_check.sh'`: passed - `USE_BAZEL_VERSION=8.6.0 bazelisk build //envpool/mujoco:mujoco_gym_envpool.so --config=test`: passed on `dev` - `USE_BAZEL_VERSION=8.6.0 bazelisk test //envpool/mujoco:mujoco_gym_deterministic_test //envpool/mujoco:mujoco_gym_align_test //envpool/mujoco:mujoco_dmc_suite_align_test --test_output=errors --cache_test_results=no --config=test`: passed on `dev` - `make bazel-build`: passed on `dev` ### Suggested Manual - Build from a clean Linux checkout and confirm MuJoCo gym/DMC environments still import without any packaged `libmujoco.so` artifact.
Configuration menu - View commit details
-
Copy full SHA for 9c6a770 - Browse repository at this point
Copy the full SHA 9c6a770View commit details -
[atari] expose ram in step info (#353)
## Summary - Problem: Issue #294 asks for Atari RAM bytes in step info, but latest main does not expose them. - Scope: Add `info["ram"]` to Atari step outputs and cover the Python Gym/Gymnasium API with regression tests; do not add a new config flag or unrelated benchmark changes. - Outcome: Atari envs now return a `uint8[128]` RAM snapshot on each reset/step alongside the existing info fields. This PR exposes ALE RAM in Atari step info on top of latest `main` and keeps the Python API/tests aligned with the new field. Closes #294. ## Technical Details - Approach: Add `info:ram` to the Atari state spec and always fill it from `env_->getRAM()` in `WriteState`, then update the Python API expectations and add regression coverage for shape, dtype, and value changes across steps. - Code pointers: - `envpool/atari/atari_env.h`: adds the state spec entry and copies the 128-byte RAM buffer into the step info payload. - `envpool/atari/api_test.py`: updates the low-level and high-level Gym API assertions to expect the new `ram` field. - `envpool/atari/atari_envpool_test.py`: adds a regression test for `info["ram"]` shape/dtype and verifies it changes after stepping. - Notes: On Linux `dev` (`nproc=1`), the repo benchmark path did not show a measurable slowdown in the stable sync case (~0.15% mean FPS delta over 3 runs). ## Test Plan ### Automated - `bazel test //envpool/atari:api_test --test_filter=_GymSyncTest.test_lowlevel_step`: PASS on Linux dev. - `bazel test //envpool/atari:api_test --test_filter=_GymSyncTest.test_highlevel_step`: PASS on Linux dev. - `bazel test //envpool/atari:atari_envpool_test --test_filter=_AtariEnvPoolTest.test_ram_info`: PASS on Linux dev. - `benchmark/test_envpool.py` on Linux dev with installed baseline vs patched wheels (3 runs each for single/sync/async): single +1.5%, sync +0.15%, async noisy; no measurable slowdown observed. ### Suggested Manual - `python -c "import envpool.atari.registration, envpool; env = envpool.make_gym('Pong-v5', num_envs=2); _, info = env.reset(); print(info['ram'].shape, info['ram'].dtype)"`: verify the exported RAM field shape and dtype. - Compare `benchmark/test_envpool.py --env atari --num-envs 12 --batch-size 12 --total-step 10000` on a multi-core Linux box if you want a lower-noise throughput check.
Configuration menu - View commit details
-
Copy full SHA for bf3262d - Browse repository at this point
Copy the full SHA bf3262dView commit details -
[docs] add Read the Docs C++ API reference (#354)
## Summary - Problem: issue #88 asks for the C++ API surface to be available on Read the Docs, but the docs currently only expose narrative guides. - Scope: add a Doxygen+Breathe docs pipeline for curated `envpool/core` headers, wire the new page into the existing Sphinx/RTD nav, and bump the package version for a docs-only patch release. - Outcome: RTD builds a browsable C++ API reference page alongside the existing `new_env` guide, without changing runtime behavior. This diff adds a generated C++ API reference to RTD and keeps the release semantics at a patch bump because the change is documentation-only. ## Technical Details - Approach: generate Doxygen XML during the Sphinx build, point Breathe at that XML, and render a curated set of core classes/types instead of dumping the entire header tree. - Code pointers: - `docs/conf.py`: configures the Doxygen XML generation hook and Breathe project mapping. - `docs/content/cpp_interface.rst`: defines the new curated C++ API reference page. - `.readthedocs.yaml`: installs `doxygen` in RTD so the docs build is self-contained. - `envpool/__init__.py`: bumps the package version to `0.9.1` for this docs-only release. - Notes: the docs link back into `content/new_env.rst`, and the version bump is intentionally `patch` because there is no API or behavior change. ## Test Plan ### Automated - `python3 -m compileall docs/conf.py`: passed locally. - `brix ssh dev -C -- 'bash /tmp/envpool_issue88_devbox.sh'`: passed on `dev`; installs docs deps, runs `make -C docs html`, and verifies `docs/_build/html/content/cpp_interface.html` contains the generated C++ API page. ### Suggested Manual - `make -C docs html`: verify the new `C++ API Reference` page appears in the Content nav. - Open `docs/_build/html/content/cpp_interface.html`: spot-check key entries like `AsyncEnvPool`, `EnvSpec`, and `PyEnvPool`. Closes #88.
Configuration menu - View commit details
-
Copy full SHA for dad453d - Browse repository at this point
Copy the full SHA dad453dView commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff v0.9.0...v0.9.1